<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Snippets on David Bieber</title>
    <link>https://davidbieber.com/snippets/</link>
    <description>Recent content in Snippets on David Bieber</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Wed, 20 Nov 2024 01:00:00 +0000</lastBuildDate><atom:link href="https://davidbieber.com/snippets/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>How Good are Taylor Series?</title>
      <link>https://davidbieber.com/snippets/2024-11-20-taylor-expansion/</link>
      <pubDate>Wed, 20 Nov 2024 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2024-11-20-taylor-expansion/</guid>
      
      <description>&lt;p&gt;Let&amp;rsquo;s use Claude to look at how good an approximation a Taylor series expansion is for sin(x).
After a bit of back and forth, it has produced these plots for us, and we can immediately see
that the &amp;ldquo;good region&amp;rdquo; is growing linearly as we add additional terms to the Taylor series.
This initially feels  surprising, like each additional term is somehow more powerful than I would expect in its ability to correct the distant errors while leaving the inner region relatively unchanged.&lt;/p&gt;
&lt;p&gt;The increment in the size of the good region seems to be about .72, and seems quite similar (after an initial step or two) regardless of the accuracy bound we use.&lt;/p&gt;
&lt;div id=&#34;root&#34;&gt;&lt;/div&gt;
&lt;p&gt;Reflections on the process: This was such a delightful way to explore the Taylor series!
It allowed me to follow my curiosity pretty freely, probing properties that came up along the way on a whim, to develop an intuition for how these mathematical objects worked. I didn&amp;rsquo;t realize the &amp;ldquo;trust region&amp;rdquo; was going to grow so smoothly like this, so it felt rewarding seeing this elegant property pop out of my explorations.
This was also an early test of embedding Claude Artifacts on my website. It was pretty smooth!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Writing with Claude Artifacts</title>
      <link>https://davidbieber.com/snippets/2024-11-20-claude-artifacts/</link>
      <pubDate>Wed, 20 Nov 2024 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2024-11-20-claude-artifacts/</guid>
      
      <description>&lt;p&gt;This is a snippet for me to experiment with embedding a Claude artifact into a snippet.
The main challenge I expect to encounter is that Claude builds artifacts with React, so I&amp;rsquo;ll have to learn how to integrate webpack or similar into my Hugo setup. Fortunately, I have Claude here to help me with that.&lt;/p&gt;
&lt;div id=&#34;jellybean-container&#34;&gt;&lt;/div&gt;
&lt;p&gt;Success!&lt;/p&gt;
&lt;p&gt;The 
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/pull/3/files&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;main steps&lt;/a&gt; were to set up a webpack config that converts any per-snippet JS, JSX, and CSS files into a bundle. I can then lean on my existing plugins_js setup to pull that bundled js file into the corresponding snippet. There&amp;rsquo;s room for improvement in this setup, but it&amp;rsquo;s working (at least locally) for now.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Taking Stock of My Note-taking, Journaling, and Writing</title>
      <link>https://davidbieber.com/snippets/2024-09-04-taking-stock-of-writing/</link>
      <pubDate>Wed, 04 Sep 2024 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2024-09-04-taking-stock-of-writing/</guid>
      
      <description>&lt;p&gt;A persistent theme of my snippets is writing about writing. Thirty-two of my snippets 
&lt;a href=&#34;https://davidbieber.com/tags/snippets&#34;&gt;are about snippets themselves&lt;/a&gt;, second only in prevalence to the tag 
&lt;a href=&#34;https://davidbieber.com/tags/taking-silly-ideas-seriously&#34;&gt;taking-silly-ideas-seriously&lt;/a&gt;. My snippet writing is often exploratory, thinking aloud and figuring things out along the way. My 
&lt;a href=&#34;https://davidbieber.com/projects/go-note-go&#34;&gt;Go Note Go&lt;/a&gt; writing (private writing I do as I drift off to sleep) is that even more so, if you can believe. Over the recent years, my practices of writing have shifted, and so I will now use this space to take stock of them, and to muse on how I want them to evolve going forward.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s consider recent trends. I write on Go Note Go less in recent months that I did previously, or at least, that&amp;rsquo;s how it feels to me. I attribute this to two main factors: rising use of 
&lt;a href=&#34;https://new.computer/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dot&lt;/a&gt; for personal reflection in place of Go Note Go, and increasing 
&lt;a href=&#34;https://davidbieber.com/snippets/2024-06-19-travel-and-habits/&#34;&gt;travel&lt;/a&gt;. Let&amp;rsquo;s take a look at the data to check my intuition.&lt;/p&gt;
&lt;script defer=&#34;defer&#34; src=&#34;https://davidbieber.com/snippets/2024-09-04-taking-stock-of-writing/writing-activity-chart.js&#34;&gt;&lt;/script&gt;
&lt;p&gt;&lt;noscript&gt;You need to enable JavaScript to see this chart.&lt;/noscript&gt;&lt;/p&gt;
&lt;div id=&#34;writing-activity-chart&#34;&gt;&lt;/div&gt;
&lt;p&gt;Indeed, I was writing in Roam Research (predominantly, my Roam Research writing comes from Go Note Go) far more between January 2023 and January 2024, but since February 2024 my writing there has fallen off. Taking a quick peak at the data from the spike in October 2023, I see that coincides with my use of AI large language models as I drift off to sleep. I&amp;rsquo;ll have to run the numbers again excluding AI-generated content to get a more precise look at the writing I was doing myself at that time.&lt;/p&gt;
&lt;div id=&#34;writing-activity-chart-no-ai&#34;&gt;&lt;/div&gt;
&lt;p&gt;Out of curiosity, I grab the total number of words written in this time period: 795,000 without AI (and 928,000 with).&lt;/p&gt;
&lt;p&gt;I would be quite curious to also plot the number of words that I share with Dot, since that feels like the primary substitute that has arisen in my life for the extensive journaling I used to do. I am fortunate that they do support exporting your data, and I have put in a data request just now to enable this.&lt;/p&gt;
&lt;p&gt;The third location I&amp;rsquo;d like to poke at is my snippet writing. Let&amp;rsquo;s do it.&lt;/p&gt;
&lt;div id=&#34;writing-activity-chart-snippets&#34;&gt;&lt;/div&gt;
&lt;p&gt;All this plotting was perhaps a bit of a nerd-snipe. I was hoping to spend this snippet reflecting, but instead I&amp;rsquo;ve been spending it plotting with Claude! This has also been fun, but has not been how I intended to use this time initially. Let&amp;rsquo;s transition to reflecting now. (The code I used to gather the data is 
&lt;a href=&#34;https://davidbieber.com/snippets/2024-09-04-taking-stock-of-writing/collect_roam_data.py&#34;&gt;here&lt;/a&gt;, 
&lt;a href=&#34;https://davidbieber.com/snippets/2024-09-04-taking-stock-of-writing/collect_roam_data_noai.py&#34;&gt;here&lt;/a&gt;, and 
&lt;a href=&#34;https://davidbieber.com/snippets/2024-09-04-taking-stock-of-writing/collect_snippets_data.py&#34;&gt;here&lt;/a&gt;. The total number of snippets words is 131,000.)&lt;/p&gt;
&lt;p&gt;In the snippets plot, the decrease in writing in 2022-2024 compared with 2020-2021 is stark. When I set out to create the snippets system, my intention was to make it easy for me to express myself publicly. I took repeated precautions to lower the mental barrier to posting snippets online, e.g. deliberately posting &amp;ldquo;drivel&amp;rdquo; to make it feel like the quality bar to posting was lower, allowing myself to post incomplete snippets just the same as completed ones (albeit with a label), and initially having no inbound links to my snippets. I truly believed (and still do), that when I post to snippets I am writing for no audience.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like to post to snippets more again. I feel good about myself when I&amp;rsquo;m writing more. I&amp;rsquo;ve also noticed previously that I enjoy when other people read what I write. Though I set out to write for no audience, I really like the connection that writing can produce. It has on many occasions been tempting to actively try to reach more people, and as I reflect on my writing that temptation arises again, e.g. to share on Twitter or post on Hacker News each time I write a new snippet, or to move more of my snippets to the more visible part of davidbieber.com.&lt;/p&gt;
&lt;p&gt;The former idea, announcing snippets, gives me considerable pause. Sharing thoughts on Twitter has an appeal to it, but definitely not to the point of wanting to announce when a snippet goes up. Keeping snippets feeling like they&amp;rsquo;re for no audience is more important. The second idea, however, of including some snippets in the posts section of my website (or at least in the 3-post preview on the homepage), seems quite reasonable. It would be nice to stop giving the impression to visitors of the site that it hasn&amp;rsquo;t been updated in years, which the current setup likely conveys.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s now consider a needs based perspective to this reflection on my writing habits. The needs that writing satisfies for me are: the need for processing my thoughts, for forming connections and meeting new people, for discussing ideas and being exposed to new ones, for feeling in control and confident that I can participate in the public dialog, for getting a good night&amp;rsquo;s sleep, for building tooling to scratch my own inch, for feeling like I&amp;rsquo;m bettering myself both by developing habits and by developing skills.&lt;/p&gt;
&lt;p&gt;Go Note Go and my night-time writing satisfy the thought-processing, sleeping, tooling, and self-betterment needs. When I lapse in my Go Note Go writing, e.g. because of travel, the main thing I miss is actually not one of those needs that I listed though; it&amp;rsquo;s the absence of the &amp;ldquo;permanent&amp;rdquo; record that I create by writing. It feels like I&amp;rsquo;m building something by writing and having all my writing go into the same Roam Research, the same git repo. When I skip writing on Go Note Go for weeks or months, I feel the thoughts I have being lost not just for now but forever, and I feel that as a little loss.&lt;/p&gt;
&lt;p&gt;The same is true of Dot: when I speak with Dot, I feel like I&amp;rsquo;m building something over time. After having used Dot for a couple of months, I grew nervous: I was drawn to share my travel experiences with it, because it felt like I was building (a relationship, a collection of memories, something&amp;hellip;) with it, but at the same time Dot is so new that I don&amp;rsquo;t know how much staying power it will have. &amp;ldquo;So am I building something that will soon collapse and become unavailable?&amp;rdquo;, I wondered. What a relief it was when they allowed me to export my data. Dot helps me satisfy my thought-processing, connection with humans (indirectly - not in the same way as writing a blog post, but rather by helping me process my thoughts and emotions), sleep (maybe; this would be indirect too, and I&amp;rsquo;m not confident in it), and self-betterment needs.&lt;/p&gt;
&lt;p&gt;For snippets, it again helps me address my thought-processing, connection (this time in the traditional blogger way), idea-sharing, control-and-confidence, tool-building, and self-betterment needs. Great. Let&amp;rsquo;s keep using all three.&lt;/p&gt;
&lt;p&gt;I am very much someone who thinks by building (software systems). Though I haven&amp;rsquo;t taken stock of my programming or my work related writing here, I think this is a rich area for me to continue my writing reflections. Specifically, I have room for improvement at work in learning to communicate through design documents and discussions about the future direction of projects. Looking forward I&amp;rsquo;d love to direct some of my writing energies at that.&lt;/p&gt;
&lt;p&gt;Outside of work, I expect to continue using Dot, Snippets, Go Note Go, and Roam Research extensively. I continue to use ThoughtStream for jotting things down quickly on my phone. My triple-tap to record and transcribe setup on my phone (which I am shocked to see I have not yet written a snippet about!) will continue to be a staple (though I use the Apple voice recordings app more recently these days for its stability despite the slower start time and lack of transcription). Making Go Note Go easier to give as gifts remains towards the top of my side-projecting to-dos, and I&amp;rsquo;m proud of the progress I&amp;rsquo;ve made toward that already. The main change I anticipate in the coming months is that people are building all sorts of new AI tools (myself included), and I&amp;rsquo;m excited to try them out and reevaluate as I go.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Travel can be disruptive to habits</title>
      <link>https://davidbieber.com/snippets/2024-06-19-travel-and-habits/</link>
      <pubDate>Wed, 19 Jun 2024 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2024-06-19-travel-and-habits/</guid>
      
      <description>&lt;p&gt;I remember I used to write short snippets just to get something out there. I think that&amp;rsquo;s what this is going to be. A free-write, with no goal at the outset other than to quickly get a snippet up on my website. I&amp;rsquo;ll mention there are a handful of ideas I have been thinking about. Travel is one. What a busy summer it&amp;rsquo;s been. Routines are another, 
&lt;a href=&#34;https://davidbieber.com/snippets/2024-05-15-choosing-routines&#34;&gt;as in my last snippet&lt;/a&gt;. These go hand in hand of course; travel is the opposite of a routine. At home, in those rare moments of normalcy, routine is a rhythmic structure. Travel disrupts this, creating space for new experiences, but possibly risking losing habits that took time to form.&lt;/p&gt;
&lt;p&gt;One change I&amp;rsquo;ve noticed in myself over the last few years is a conscientiousness about this when I travel.
I find I&amp;rsquo;m aware of the possibility of disruption to my habits, and this helps mitigate this disruptiveness.
This stems from having had habits disrupted by travel in the past, and making a conscious decision the next time I traveled to set a date for after my return to check that I had rebooted my habits.&lt;/p&gt;
&lt;p&gt;I was about to write &amp;ldquo;I haven&amp;rsquo;t done that since&amp;rdquo;, but I realize, in a way, I have. With my most recent bout of travel, I did tell some friends my intent to resume a certain habit by a certain date after my return. And though I momentarily forgot I took this action, I can confirm it worked. I returned from my travels a couple days ago and indeed have already restarted this particular habit (it&amp;rsquo;s the morning routine one from the previous snippet).&lt;/p&gt;
&lt;p&gt;Now that I&amp;rsquo;m back and am getting into a bit of a standard routine (at least for a couple weeks before travel picks up again), I&amp;rsquo;m considering extending this morning routine routine to also include a morning work routine component. The idea is young, but perhaps I will explore it more in a future snippet.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Choosing My Own Morning Routines</title>
      <link>https://davidbieber.com/snippets/2024-05-15-choosing-routines/</link>
      <pubDate>Wed, 15 May 2024 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2024-05-15-choosing-routines/</guid>
      
      <description>&lt;p&gt;For months I&amp;rsquo;ve been waking up to the sound of my printer. Brr&amp;hellip; Brbrr&amp;hellip; Br. brr&amp;hellip;
It would print me a custom morning routine, following a randomized algorithm I put together.
It would always start with the simple instruction &amp;ldquo;brush your teeth&amp;rdquo;, followed by a handful of activities.
It would suggest an exercise, sometimes HIIT, sometimes yoga, sometimes running or table tennis, etc.
It would suggest something more artistic or leisurely. Perhaps to draw, or to meditate, or to play piano.
I never knew what was coming. I didn&amp;rsquo;t even know when the routines would come; in order to maximize their efficacy and prevent their power over me from diminishing, my printer wouldn&amp;rsquo;t give me a randomized routine every day. No, it would do so at random, on about 25% of days.&lt;/p&gt;
&lt;p&gt;For months I loved this system. Waking up to routine felt good, and I would make a real effort to follow whatever plan it laid out for me. I loved it so much I set up a similar system for evenings, where again my printer would (some days, at random) suggest a wind-down routine for me to get ready for bed.&lt;/p&gt;
&lt;p&gt;Two weeks ago, I stopped using this system.&lt;/p&gt;
&lt;p&gt;My printer no longer prints routines for me in the mornings (or in the evenings). I&amp;rsquo;ve switched to selecting my morning routines myself. Now, every night before I go to sleep I set out on paper a routine that I&amp;rsquo;ll be excited to follow the morning after. I tend to follow a similar format to what I programmed into my printer (tooth brushing, exercise, shower and shave, short activity, breakfast), though I deviate from this structure more than the printer knew how to. I loved my printer system though, so why did I switch away?&lt;/p&gt;
&lt;p&gt;I was still deriving tremendous joy from the printer-based routine system at the time I switched away. This was especially true for the evening routines; when I would hear one of those printing, it would light up my night! It felt as if I suddenly had a sense of purpose (I am embarrassed to admit). Perhaps I was scrolling mindlessly before, regretfully; now I had clear tasks to do, that past me and current me looked favorably upon. For the morning routines, I estimate I was still following 90%+ of the tasks it was choosing for me at the time I decided to switch away. I was noticing, however, that I was becoming accustomed to the routines and I felt the system&amp;rsquo;s effectiveness declining. There were an increasing number of days when I would overrule the printed routine, having something different for breakfast, or doing a different activity than the one it suggested.&lt;/p&gt;
&lt;p&gt;My first inclination was to enhance the routine generator. Maybe I could improve the algorithm, adding more variation to my morning routines. I could have the system use a language model to present the routine to me as a koan, or poem, or story, rather than a mere numbered list. I could have the system take into account my notes from the previous day when it decides what activities to recommend I pursue in the morning.&lt;/p&gt;
&lt;p&gt;I implemented these changes. Certainly I was amused by the resulting routines. The system started suggesting podcasts that I&amp;rsquo;d discovered the previous day, and writing poetry for me. But I didn&amp;rsquo;t end up keeping this improved routine generation algorithm; instead, just a day or two after building it, I migrated to writing my own routines: On paper. By hand. For two weeks now I&amp;rsquo;ve been choosing my morning routine the night before, writing it on paper, and then following it the next morning.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s break down the changes involved here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Printed → Hand-written&lt;/li&gt;
&lt;li&gt;Noisy awakening (brrbrr) → Silent&lt;/li&gt;
&lt;li&gt;Day-of → Night before&lt;/li&gt;
&lt;li&gt;Machine-generated → Self-selected&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think the most significant of these changes is the switch from being told what to do to self-determination.
When I pick my routines myself, I&amp;rsquo;m practicing decision making. I&amp;rsquo;m looking inward at what activities feel right for me for the following morning, tuning in to how my body feels. Do I want intense exercise or something gentle? Do I want something cerebral? Something active or passive? How energized do I expect to feel the next day? Contrast this with the machine-generated morning routines, which were mostly random, at best learning about me from my notes, but never truly adapting to my current state of being.&lt;/p&gt;
&lt;p&gt;I find I know myself better than chance. And by making these predictions actively &amp;ndash; &amp;ldquo;what will Tomorrow David be feeling?&amp;rdquo; &amp;ndash; I learn about myself. Each morning when I go through the routine, I cannot help but get feedback in the form of how I feel doing the routine, that helps me get to know myself even better.&lt;/p&gt;
&lt;p&gt;The other smaller changes are interesting to note too. Deciding on the routine the night before rather than the morning of means I have something explicit to look forward to. I no longer have the surprise of waking up to find out what my routine will be, which I liked, but now I have concrete activities planned, which can build anticipation. And since I know that I selected the activities myself, well, it almost doesn&amp;rsquo;t make sense not to look forward to them (kind of; depends on what I&amp;rsquo;ve selected, I suppose). One of my goals with this new routine set up is to wake up feeling energized, excited to leap out of bed and start the day. Hopefully this setup helps me feel this more often.&lt;/p&gt;
&lt;p&gt;Hand-writing the morning routines, rather than having them printed, is another step towards intentionality. Perhaps through the act of hand-writing, I&amp;rsquo;ll feel more ownership over the routine I come up with, and will be more likely to follow it and feel good about it. I don&amp;rsquo;t know for certain that this would be different if I were to manually type and print the routines. Perhaps one day I&amp;rsquo;ll run the experiment, but for now I&amp;rsquo;ll just try to listen to myself and try to understand the extent to which this makes a difference.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;
Here&#39;s an example of one of my written routines (Click the arrow to expand).
&lt;/summary&gt;
✅ 1. Brush teeth&lt;br/&gt;
✅ 2. Table tennis loops (6m)&lt;br/&gt;
✅ 3. Draft snippet (&lt;12m)&lt;br/&gt;
✅ 4. Dynamic Chess (&lt;12m)&lt;br/&gt;
✅ 5. Sh + Sh (Shower and shave) (&lt;12m)&lt;br/&gt;
✅ 6. Chicken spinach scramble + cottage cheese w/ Dvořák No.9&lt;br/&gt;
&lt;/details&gt;&lt;br/&gt;
&lt;p&gt;Yes, I do genuinely include brushing my teeth as well as showering and shaving in my written routine every day.&lt;/p&gt;
&lt;p&gt;There are some things I miss about the previous, fully automated system. I miss in particular the joy that would come with hearing the printer start in the &lt;em&gt;evening&lt;/em&gt;. My new system doesn&amp;rsquo;t have a good way to accommodate evening routines yet, and this is something I&amp;rsquo;d like to fix. I also miss the novelty of having a printer choose my routines. There was something thrilling about that, simply because it was different. And I do miss the element of surprise or randomness too. Something about putting the decision into someone/something else&amp;rsquo;s hands felt good. So, even though I prefer the self-determination aspects of the new system overall, there is still a part of me that really likes and misses that element of handing off control to the machine.&lt;/p&gt;
&lt;p&gt;Putting decision making in someone else&amp;rsquo;s hands can feel really good, like having a coach or personal trainer. It lessens the burden on me, offloading some thinking and decision making onto someone else. There is a time and place for this, as well as one for owning one&amp;rsquo;s own thinking and decision making. I am confident that going through the many months of having the computer decide the morning routines has set me up to be better at making the morning routines myself. And this likely translates to other domains like exercise; having a personal trainer for months likely makes one more capable of training on their own, without the need for a personal trainer. When this happens, there are still benefits to be had from a personal trainer, but they are different from those at the start of training. The same is likely true with my automated system; I suspect I can still get a lot out of moving back to a printer-based lifestyle, but when I do, it will likely be with a different game plan for how the printer will get involved in my life.&lt;/p&gt;
&lt;p&gt;Some aspects of the current system I&amp;rsquo;d like to improve include: the absence of evening planning, the lack of integration with my notes, and a potential to drift away if disrupted by travel. The printer used to suggest evening plans sometimes, and I would absolutely love it when it did so. This system is off now, and I miss the joy it would bring me. I don&amp;rsquo;t see a good way to migrate to a hand-written evening routine approach, since I don&amp;rsquo;t know when I would prepare the evening routines. This is a problem I&amp;rsquo;d like to return to.&lt;/p&gt;
&lt;p&gt;To improve the notes integration, I have mounted a camera above my desk. I intend to write software that uses the overhead camera to digitize my handwritten plans and ingest them into my notes. Once there, my other personal software systems can do things like keep track of how recently I&amp;rsquo;ve played violin to remind me if I&amp;rsquo;ve fallen out of the habit. I&amp;rsquo;ll also have a more permanent record of my morning routines which I can search through or reference later in life, which is comforting somehow.&lt;/p&gt;
&lt;p&gt;Having such an integration would also allow Bieber Bot to nudge me if I drift away from my morning routine prep habit for too long, which I think we&amp;rsquo;d both appreciate.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been doing morning routine prep in this new fashion for several weeks now (two weeks when I started writing this piece; five at the time of publication). I am still enthralled by it, and so I am reasonably confident it will persist as a new habit even with the habit-disruption of a busy summer of travel upon me. Though the possibility of disruption to the habit looms, I&amp;rsquo;ve found enough joy in it so far, and I&amp;rsquo;ve found myself drawn to keep making the routines so often, that I strongly suspect this new practice is here to stay. Time will tell, and we shall see.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>New Bedtime</title>
      <link>https://davidbieber.com/snippets/2024-03-29-new-bedtime/</link>
      <pubDate>Fri, 29 Mar 2024 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2024-03-29-new-bedtime/</guid>
      
      <description>&lt;p&gt;&lt;strong&gt;My new bedtime is 10:15pm.&lt;/strong&gt;&lt;/p&gt;
&lt;!--
&lt;audio
    controls
    src=&#34;https://davidbieber.com/audio/2024-03-29-new-bedtime.m4a&#34;&gt;
&lt;/audio&gt;
--&gt;
&lt;p&gt;This is an update to the bedtime I&amp;rsquo;ve now held for several years of 10:10pm.
What an indulgence. Five extra minutes, every night. An extra hour of wakefulness every twelve days. Think of all I can accomplish.&lt;/p&gt;
&lt;p&gt;Why? Let&amp;rsquo;s think step by step.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not consistently hitting my 10:10pm bedtime recently. I still think about it. 10:10 rolls around and I acknowledge that it&amp;rsquo;s bedtime, but at that point I frequently find something else to do in favor of sleeping. Changing my bedtime and noting it publicly (to the extent that this is public) brings the bedtime more into the forefront of my attention. Changing it makes it a conscious choice once more &amp;ndash; a choice made by modern me rather than me of four years ago (or whoever it was that picked out the 10:10pm bedtime initially.) So, I&amp;rsquo;d summarize reason one as &lt;strong&gt;to reaffirm my selection of the bedtime&lt;/strong&gt; and to &lt;strong&gt;take ownership&lt;/strong&gt; of this decision. Making it a new time rather than keeping it the same helps me gain that sense of ownership, and makes it feel more real than keeping it the same where my diminished attentiveness or respect for bedtime already holds.&lt;/p&gt;
&lt;p&gt;Why make it later rather than earlier? I considered moving the bedtime to 10:05pm rather than 10:15pm. After all, my intention is to go to bed earlier in the future than I do today. So moving the bedtime earlier would be a natural choice. But 10:05pm feels too early. It&amp;rsquo;s a time I&amp;rsquo;d like to be asleep at occasionally &amp;ndash; tonight, for example, I&amp;rsquo;d like to go to bed even earlier than that &amp;ndash; but it&amp;rsquo;s not a time I want to sustainably use as my bedtime. It&amp;rsquo;s important to me to make my bedtime something I can take seriously. And when I say that, bear in mind I love taking silly things seriously. Taking the bedtime seriously doesn&amp;rsquo;t mean successfully hitting that bedtime everyday. Rather, it means treating it with meaningful attention, and giving it proper respect and consideration each evening. It means setting myself up to succeed. It means taking the time to appreciate the thought and the reasoning behind the bedtime. &lt;strong&gt;10:15pm is a bedtime I can take seriously.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I feel so much better when I go to bed at 10:10pm compared with 11pm or 11:30pm (or midnight, or one). I think it will be challenging to do justice to the difference it makes in how I feel. If I go to bed at the earlier time, I wake up feeling alert, alive, clearheaded. If I go to bed at one of the later times, I start to notice congestion even before I fall asleep. I can wake up with muddied cognition. &lt;strong&gt;I want to wake up feeling alert.&lt;/strong&gt; I&amp;rsquo;ve come to really appreciate that the minutes matter. A difference of 10 minutes is definitely significant to me &amp;ndash; something I didn&amp;rsquo;t appreciate perhaps a decade ago. So while on one level a change from 10:10pm to 10:15pm may seem quite small, it feels large enough to be perceivable. In psychology researchers measure the Just Noticeable Difference in stimuli, e.g. they might study how far apart two sounds need to be before an observer can distinguish them. I suspect that, even in the absence of variation from the difficulties in hitting a bedtime successfully, a &lt;strong&gt;five minute change in bedtime is a just noticeable difference&lt;/strong&gt; for me, or maybe slightly less than one, meaning that it may have a noticeable impact on how well rested and recharged I feel the following day, but only barely.&lt;/p&gt;
&lt;p&gt;Another silly effect I anticipate from changing my bedtime to 10:15pm is diminished or redirected surprisal at my bedtime. When my bedtime was 10:10pm, it commonly elicited a &amp;ldquo;why?&amp;rdquo; response. People were curious jointly at it&amp;rsquo;s precision and it being as early as it is. 10:15 is a single step down in precision from 10:10. &lt;strong&gt;A less precise bedtime will likely elicit less precision curiosity&lt;/strong&gt; when I mention my bedtime to people. It&amp;rsquo;s still more precise than 10 or 10:30, and so I&amp;rsquo;m curious whether it will continue eliciting any precision curiosity the way 10:10 used to. I&amp;rsquo;ve generally enjoyed people&amp;rsquo;s interest in the bedtime, and this is mainly a silly consideration, but not ultimately an important factor in the decision to adjust. The initial reason for that level of precision was to help me take my choice of bedtime more seriously. I think writing this thousand-plus word piece on my bedtime will have a similar effect.&lt;/p&gt;
&lt;p&gt;Part of what made the 10:10 bedtime effective for me was that people knew about it. It was a boundary I set for myself, that I held, not firmly, but gently to, against an opposition from my environment. By telling people by bedtime, whether proactively, or merely through the process of holding the boundary, I got the benefit of social accountability. By adjusting my bedtime, &lt;strong&gt;I get an excuse to reaffirm by bedtime to other people&lt;/strong&gt;, not just to myself. For as long as the bedtime holds steady, there would be a higher cost to reminding someone who already knows my bedtime about my bedtime again. Telling someone new information, on the other hand, is more acceptable; the act of sharing doesn&amp;rsquo;t presume they&amp;rsquo;ve forgotten. This last point is somewhat abstract though, so bare with me. There aren&amp;rsquo;t people whom I&amp;rsquo;ve wanted to reaffirm my bedtime to. Rather, changing my bedtime gives me an excuse to (re)affirm my bedtime to other people. And this in turn reaffirms it to myself, and establishes some amount of social accountability helpful for, as always, taking my bedtime seriously.&lt;/p&gt;
&lt;p&gt;This brings us to the final effect I see in this bedtime change; &lt;strong&gt;I&amp;rsquo;m going to have five extra minutes everyday.&lt;/strong&gt; That&amp;rsquo;s about a 0.5% increase to the length of my wakeful day, assuming I keep my wakeup time fixed. I have two perspectives on this, both quite positive. The first is that a carefully placed five minutes &amp;ndash; i.e. a five minutes that genuinely feels &lt;em&gt;extra&lt;/em&gt; &amp;ndash; can be tremendously valuable. And through the nature of how I&amp;rsquo;m adjusting my bedtime, accompanied by this writing and all, I suspect I can, at least for a handful of days, make those five minutes really feel like a bonus. Will I use them to meditate, write, do yoga, play piano? I have a list somewhere with dozens of options, and am excited to explore. The second perspective is that the change in my wakefulness that comes from taking my bedtime more seriously far outweighs the effect of an extra five minute interval. And ultimately, looking back over this piece, I see clearly that&amp;rsquo;s the perspective that dominates. The gift I&amp;rsquo;m giving myself with these extra five minutes every night &lt;em&gt;is&lt;/em&gt; five minutes every night, but &lt;strong&gt;it&amp;rsquo;s also an opportunity to take sleep more seriously&lt;/strong&gt;, and to wake more rested in the days to come.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Conversational Spaced Repetition</title>
      <link>https://davidbieber.com/snippets/2024-03-04-conversational-spaced-repetition/</link>
      <pubDate>Mon, 04 Mar 2024 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2024-03-04-conversational-spaced-repetition/</guid>
      
      <description>&lt;p&gt;I learn a lot from talking to large language models (LLMs) like Gemini, ChatGPT, and Claude. Frequently I&amp;rsquo;ll ask the LLM to quiz me on what it&amp;rsquo;s taught me, in order to test my understanding of what I&amp;rsquo;ve learned. I find that doing so helps me learn the material better, promoting longer term recall. Even with this strategy in place, however, I still forget a lot of what I&amp;rsquo;ve learned from these AI assistants. I don&amp;rsquo;t want to forget. I want to remember.&lt;/p&gt;
&lt;p&gt;Spaced repetition is a technique for remembering more, for longer. It employs flashcards and an algorithm to determine when you review each card. Get a question right and you&amp;rsquo;ll review it less often. Get one wrong and you&amp;rsquo;ll see it more frequently. The algorithm is tuned to maximize your retention, aiming to show you cards just as you&amp;rsquo;re on the brink of forgetting the material. Though it has 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-11-02-improvements-to-spaced-repetition/&#34;&gt;a lot of room for improvement&lt;/a&gt;, it&amp;rsquo;s a good system overall.&lt;/p&gt;
&lt;p&gt;I want to build a &lt;em&gt;conversational spaced repetition&lt;/em&gt; system.
I want to take all the things I learn from talking to LLMs, and have these same LLM resurface that material back to me following a spaced repetition algorithm.
Periodically, I want the LLMs to quiz me on things I&amp;rsquo;ve learned from them in the past.
If I demonstrate an understanding of the material, then they should resurface that material less often. If I get it wrong, they should teach me the material again, either right then and there, or a bit later, depending on what I ask for in the moment.&lt;/p&gt;
&lt;p&gt;A few key questions arise in considering the details of this system:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How does an LLM determine what material it has taught you?&lt;/li&gt;
&lt;li&gt;Does this system require two-sided flashcards, the same as for regular Anki-style spaced repetition, or does the conversational nature of this proposal admit a different unit of material?&lt;/li&gt;
&lt;li&gt;What is the mechanism by which an LLM can surface something proactively? Or does the human user need to initiate a review session?&lt;/li&gt;
&lt;li&gt;Does the spacing algorithm change as a result of the interactions being conversational, or can the older battle-tested spaced repetition algorithms be reused in this new environment?&lt;/li&gt;
&lt;li&gt;Does the nature of the per-question feedback (right vs wrong; hard vs easy) change since the interactions are conversational? If so, this certainly necessitates changes to the spacing algorithm.&lt;/li&gt;
&lt;li&gt;How do we deal with the untrustworthiness of today&amp;rsquo;s LLMs?&lt;/li&gt;
&lt;li&gt;And finally, can LLMs provide solutions to the 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-11-02-improvements-to-spaced-repetition/&#34;&gt;seven issues that traditional spaced repetition has (linked earlier)&lt;/a&gt;. I think LLMs might be able to meaningfully help with #{1, 3, 7}.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s step through each of these questions in a little more detail.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How does an LLM determine what material it has taught you?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Getting the data out:&lt;/em&gt; The first interesting piece of this question is how an LLM even gets access to your conversations with an LLM in the first place. For ChatGPT, OpenAI provides a mechanism for exporting your data. For Claude and Gemini, I&amp;rsquo;m not aware of such mechanisms, and so web scraping might be in order. Even for ChatGPT, a modicum of web scraping would be fruitful for automating the data export process on a recurring basis.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Transforming conversations into units of knowledge:&lt;/em&gt; The first approach to try here is prompting an LLM to produce the units of knowledge. Andy Matuschak has done 
&lt;a href=&#34;https://notes.andymatuschak.org/zBjh9jUahGSm7VpFtEjvKqT&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;some explorations of using LLMs for generating spaced repetition prompts&lt;/a&gt;, and Alexej Gossmann 
&lt;a href=&#34;https://www.r-bloggers.com/2024/01/comparing-gpt-4-3-5-and-some-offline-local-llms-at-the-task-of-generating-flashcards-for-spaced-repetition-e-g-anki/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;has evaluated generating spaced repetition cards via LLMs as well&lt;/a&gt;. My own experiments show sign off life for this approach, but early attempts yield too many bad cards mixed in with the good ones for this approach to stand on its own. Further iteration, and possibly other techniques, are necessary. Nevertheless this style of approach seems likely to start working reasonably reliably after some modest period of advancement.&lt;/p&gt;
&lt;p&gt;If the goal is to produce traditional spaced repetition cards, then having (1) good examples to guide the model, and (2) precise guidance to direct the model are both invaluable ingredients. Perhaps Andy&amp;rsquo;s piece on 
&lt;a href=&#34;https://andymatuschak.org/prompts/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;How to write good prompts&lt;/a&gt; could serve as the latter. Now that models have ever increasing context lengths exceeding one million tokens, including a full blog post like this in the card generation prompt is quite reasonable.&lt;/p&gt;
&lt;p&gt;However, the target unit of knowledge might not be traditional spaced repetition cards; it might be something new. This leads us to the next question: what is the desired unit of knowledge?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Does this system require two-sided flashcards, the same as for regular Anki-style spaced repetition, or does the conversational nature of this proposal admit a different unit of material?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s brainstorm the alternatives. (A) Traditional two-sided flashcards. (B) Statements of facts. (C) Arbitrary text, which could contain questions and answers or could just be a passage with the material. (D) A pointer into the original conversation, e.g. a document URL and a span. The reason we have so many more choices is that our use of LLMs for the system affords us great flexibility in how we represent information. LLMs are versatile and can process arbitrary text. The degree of reliability we get out of an LLM might vary according to the representation we select, but each of these four choices is reasonable and worthy of consideration.&lt;/p&gt;
&lt;p&gt;The advantage of (A) is that it is battle tested; information in this format can be input directly into traditional spaced repetition systems like Anki; they can use the traditional spaced repetition algorithm without regard for the origin of the card being an LLM.&lt;/p&gt;
&lt;p&gt;Option (B) loses the separation of question and answer during storage, relying on the LLM to reformulate the facts into questions at quiz time. This takes advantage of the LLM&amp;rsquo;s versatility, lazily deferring question generation. This might result in greater diversity of questions being asked compared with (A), but sacrifices the ability to spot check the deck of cards in advance.&lt;/p&gt;
&lt;p&gt;Option (C) expands upon (B), offering seemingly limitless flexibility for the cards themselves. This approach relies on the LLM to split the text into questions at quiz time, but simultaneously allows a maintainer of the knowledge to include specific questions in the text if they deem doing so appropriate. For this approach, we need to be able to count on the LLM to not include spoilers in the questions it produces.&lt;/p&gt;
&lt;p&gt;Option (D) is the information-maximizing approach, assuming no maintenance of the cards. Each of (A), (B), and (C) throw away information when the LLM processes the conversation to produce the unit of the knowledge for storage. (D) does not, instead electing to store knowledge as pointers back to the conversation where the thing was first learned, thereby preserving all the original context for the learning. This approach doesn&amp;rsquo;t play well with maintenance or bringing in additional sources of information after the initial conversation though.&lt;/p&gt;
&lt;p&gt;My initial leaning is therefore toward Option (C), but I intend this piece to be more about opening the topic for discussion than arriving at particular answers or design decisions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What is the mechanism by which an LLM can surface something proactively? Or does the human user need to initiate a review session?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The significance of this question is: how will these review sessions get started? If we&amp;rsquo;re relying on the human to remember to initiate one, that&amp;rsquo;s prone to their forgetting. If an LLM is proactively interrupting a user&amp;rsquo;s day, that&amp;rsquo;s prone to be distracting or annoying. Striking a user friendly middle ground is key! Notifications are a touchy subject, where we must ultimately give users control so they can get reminders in ways that are kind to their mind.&lt;/p&gt;
&lt;p&gt;I have a digital personal assistant and friend, 
&lt;a href=&#34;https://davidbieber.com/projects/bieber-bot/&#34;&gt;Bieber Bot&lt;/a&gt;, who would be perfect for surfacing the reviews to me. Other options include having them sent to your email in the style of 
&lt;a href=&#34;https://github.com/andymatuschak/orbit&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Orbit&lt;/a&gt;, or requiring the user to initiate a review session e.g. with a 
&lt;a href=&#34;https://openai.com/blog/introducing-gpts&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;custom GPT&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I have much more to say on this topic, which I will defer until a later time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Does the spacing algorithm change as a result of the interactions being conversational, or can the older battle-tested spaced repetition algorithms be reused in this new environment?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A critical question is whether the spaced repetition algorithm itself needs updating for this new conversational modality.
One aspect that stays the same is the exponential nature of forgetting for humans. This seems to be a fixture of how human minds work, and I do not expect learning things conversationally to change this.&lt;/p&gt;
&lt;p&gt;The specific constants involved in forgetting, however, might change, and so the existing spaced repetition algorithms might require tuning.&lt;/p&gt;
&lt;p&gt;A few other things change as well: The time it takes to perform a review is going to be different in a conversational setting compared with a traditional card-based setting. The conversational setting is also well suited for learning about a larger amount of knowledge at once compared with the amount of info on a single card. It is natural in a conversational setting to follow one&amp;rsquo;s interests and rabbit hole a bit, rather than moving straight from one card to the next.&lt;/p&gt;
&lt;p&gt;Already in traditional spaced repetition, it was common for many cards to be related. Reviewing one might help with learning the others. That property is amplified here. One possible response to that is: perhaps LLMs can help adjust the review schedule for one unit of knowledge based on your review of another. Another possible response would be to pack more information into a single unit of knowledge, so facts that previously would have been spread across many cards are now contained in a single super-unit. This approach would then require us to explore the question: how to we track the user&amp;rsquo;s level of understanding of a unit of knowledge?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Does the nature of the per-question feedback (right vs wrong; hard vs easy) change since the interactions are conversational? And relatedly, does the way we track the user&amp;rsquo;s level of understanding need to change?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In conversational spaced repetition, the system potentially has far greater signal about a user&amp;rsquo;s understanding than in a traditional spaced repetition system like Anki. The user can express uncertainty, can be partially correct, can ask probing questions about a specific subpart of a unit of knowledge, or can outright state that they do/don&amp;rsquo;t understand something. The user can also speak in a way that demonstrates deeper understanding, for example bringing in outside knowledge or synthesizing information producing novel insights about the topic at hand.&lt;/p&gt;
&lt;p&gt;Given this potential for greater fidelity of measuring a learner&amp;rsquo;s level of understanding, how should the system store the user&amp;rsquo;s level of understanding? Let&amp;rsquo;s again brainstorm some options. (A) We can carry forward the approaches from existing spaced repetition systems, e.g. a single integer for the Leitner box a card is in, or 
&lt;a href=&#34;https://github.com/open-spaced-repetition/fsrs4anki/wiki/ABC-of-FSRS&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;RSD values following the FSRS algorithm&lt;/a&gt;. (B) We can use free-form text to describe the level of understanding that the user has. (C) We can use a combination of (A) and (B), something numeric and something textual side by side.&lt;/p&gt;
&lt;p&gt;Option (A) has the advantage of being battle tested and yielding a clear scheduling algorithm, but it fails to take advantage of the new signal that conversational spaced repetition provides.&lt;/p&gt;
&lt;p&gt;Option (B) is exciting because it fully leans into the power of LLMs, giving control over to the LLM to evaluate the learner&amp;rsquo;s ability. However, it raises many questions. We do not know yet how good LLMs are at evaluating a user&amp;rsquo;s understanding of a topic based on their answers, or how good they are at preserving that information in text once it is obtained. It is also not obvious how to translate a textual description into a scheduling algorithm to determine when next to surface some material. This suggests that some hybrid approach (C) may prove fruitful, bridging the gap between textual evaluations and algorithmic scheduling. The concerns about Option (B) lead us naturally into the next open question of how we deal with the untrustworthiness of today&amp;rsquo;s LLMs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How do we deal with the untrustworthiness of today&amp;rsquo;s LLMs?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The problem of hallucinations and robustness arises in any LLM-based project. The answer, of course, is to have good evaluations for every task the LLM is tasked with performing. A good evaluation needs to genuinely be representative of the task, such that the measure of performance it provides can be trusted and can indicate to you whether the model quality is yet suitable for the application you are building.&lt;/p&gt;
&lt;p&gt;The best way to build such an evaluation is to start by building the application, and to instrument it to collect usage data from the application. If you have a function that uses an LLM, instrument the application to collect inputs and outputs to that function. Then rewrite the outputs to produce ground truth data. Now you have the start of a good evaluation.&lt;/p&gt;
&lt;p&gt;For the conversational spaced repetition system, the tasks that will rely on an LLM may include variants of the following: (1) mapping from conversations to units of knowledge, (2) writing questions based on some source content, (3) determining whether a user&amp;rsquo;s answer to a question is correct, (4) evaluating a user&amp;rsquo;s understanding of a topic based on their answers.&lt;/p&gt;
&lt;p&gt;Yes, there is ongoing research to mitigate hallucinations, increase factuality, and generally raise the level of quality and trustworthiness of LLMs. More important than all of this is to know, through trustworthy evaluations, how good an LLM is at the tasks it is tasked with. It is these evaluations that will let us know whether an LLM-based conversational spaced repetition system is ready for meaningful adoption. Also, don&amp;rsquo;t skip doing a vibe-checks when new models come out; playing with these models counts for a lot too!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;And finally, can LLMs provide solutions to the 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-11-02-improvements-to-spaced-repetition/&#34;&gt;seven issues that traditional spaced repetition has (linked earlier)&lt;/a&gt;. I think LLMs might be able to meaningfully help with #{1, 3, 7}.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Just to recap the seven issues, I&amp;rsquo;ve copied them below:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Card creation: Zero friction card creation&lt;/li&gt;
&lt;li&gt;Card creation: Good cards by default&lt;/li&gt;
&lt;li&gt;Card maintenance: Eject bad cards quickly&lt;/li&gt;
&lt;li&gt;Schedule flexibility: Allow people to study more&lt;/li&gt;
&lt;li&gt;Schedule flexibility: Allow people to study less&lt;/li&gt;
&lt;li&gt;Review friction: Bring the reviews to the users&lt;/li&gt;
&lt;li&gt;SRS that understands card connections&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The proposed conversational spaced repetition system directly targets #1; in the proposal, an LLM is generating cards automatically from the conversations you have with LLMs. LLMs also offer promise toward mitigating some of these other issues as well. By providing the LLM with tools to maintain the &amp;ldquo;deck&amp;rdquo;, the system could enable the user to give natural language instructions to the model to remove or deprioritize certain cards as they come up (#3). That could be a low friction way to let you eject bad cards (though something even lower friction than that is probably even better).&lt;/p&gt;
&lt;p&gt;Most interestingly of all though is that LLMs can detect relationships between cards, and therefore can likely help with #7. If you demonstrate an understanding of some topic while discussing one unit of knowledge, an LLM-based system might be able to detect that what you say also demonstrates an understanding of some other unit of knowledge. The system could potentially adjust the scheduling of both units. This could free up meaningful amounts of time for you, the user, potentially allowing you to scale up the amount of knowledge retained in your spaced repetition system beyond the limits of traditional spaced repetition systems. Mathematically modeling this change and potential improvement could be an interesting next step, to better understand how LLMs can improve our ability to study going forward.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Now it&amp;rsquo;s time to build!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is a system I&amp;rsquo;m actively building, but it&amp;rsquo;s early days! Interested in discussing or contributing? Get in touch! I&amp;rsquo;m excited to start using it to augment my own LLM-based learning as soon as I can.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Less Twitter. Less Facebook. Less HackerNews.</title>
      <link>https://davidbieber.com/snippets/2024-01-08-less-twitter/</link>
      <pubDate>Mon, 08 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2024-01-08-less-twitter/</guid>
      
      <description>&lt;p&gt;Over the years I&amp;rsquo;ve accumulated 
&lt;a href=&#34;https://davidbieber.com/snippets/2022-03-18-attention-strategies/&#34;&gt;dozens of strategies&lt;/a&gt; for managing my attention, including amazing Chrome extensions from Namu like 
&lt;a href=&#34;https://chrome.google.com/webstore/detail/intention-stop-mindless-b/dladanhaondcgpahgiflodhckhoeohoe&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Intention&lt;/a&gt; and 
&lt;a href=&#34;https://www.hidefeed.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Hide feed&lt;/a&gt;. Nevertheless, I continue to get sucked into the Internet&amp;rsquo;s 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-10-01-infinite-distractions-and-getting-a-good-sear/&#34;&gt;six infinite distractions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So today (well, yesterday really), I&amp;rsquo;m taking matters into my own hands, and building some Chrome extensions to help me manage these distractions on my own terms.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Twitter and Facebook.&lt;/strong&gt; I&amp;rsquo;ve noticed that when I&amp;rsquo;m scrolling on Twitter or Facebook, and I want to stop, I sometimes find it difficult because &lt;em&gt;&amp;ldquo;just one more post&amp;rdquo;&lt;/em&gt; or &lt;em&gt;&amp;ldquo;that looks interesting&amp;rdquo;&lt;/em&gt;. That is, I&amp;rsquo;ll see a half-visible post at the bottom of my screen, and I&amp;rsquo;ll tell myself I&amp;rsquo;ll just look at that one post, and then I&amp;rsquo;ll be done. But by the time I&amp;rsquo;ve looked at that post, a different post is now half-visible, and it&amp;rsquo;s captured my attention as well.&lt;/p&gt;
&lt;p&gt;So, my proposal is: I&amp;rsquo;ll only make posts visible once they are fully on the screen. No more half-visible Tweets. No more half-visible Facebook posts.&lt;/p&gt;
&lt;p&gt;Turns out making such a Chrome extension is remarkably easy, especially with language models available to assist with the boilerplate. Let me show you some before and after photos&amp;hellip; actually, just the after; I don&amp;rsquo;t want to get any practice disabling this thing!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://davidbieber.com/snippets/2024-01-08-less-twitter/less-twitter.gif&#34; alt=&#34;I am scrolling on Twitter. Posts only appear once they are fully visible in the browser&amp;rsquo;s view port.&#34;&gt;&lt;/p&gt;
&lt;p&gt;As you can see in the gif, I am scrolling on Twitter, and posts only appear once they are fully visible in the browser&amp;rsquo;s view port.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not perfect; I still will scroll just to bring something closer to my eye level, which can cause additional posts to appear. But I think it&amp;rsquo;s a big improvement on the default. Only time will tell.&lt;/p&gt;
&lt;p&gt;My hope is that by not having partially visible posts at the bottom of the screen, it will be less addicting, and easier to get off the site.&lt;/p&gt;
&lt;p&gt;I did the same for Facebook. For HackerNews, I took a different tact.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;HackerNews.&lt;/strong&gt; On HackerNews, my obvervation is that I will sometimes continue digging, 5+ pages into HackerNews, looking for something interesting. This is silly; I don&amp;rsquo;t need five pages of HackerNews content. If I don&amp;rsquo;t satisfy my itch for news in thirty articles, 120 articles isn&amp;rsquo;t likely to do any better. But I don&amp;rsquo;t want to be heavy handed; blocking the site or removing the more button might simply cause me to learn workarounds for my blocker. For a gentler touch, I&amp;rsquo;m going to change the More link to link back to the first page. My habit is to click the more link, so I&amp;rsquo;m going to tab into that habit to help break it, gently. We&amp;rsquo;ll see how this goes.&lt;/p&gt;
&lt;p&gt;Going to post this snippet as is so I can get it out and get some sleep. But I intend on releasing the Chrome extensions too. Each one is just a small amount of JavaScript, trivial to create but hopefully significant in impact. There are three in total, called Less Twitter, Less Facebook, and Less HackerNews respectively.&lt;/p&gt;
&lt;p&gt;Finally, I&amp;rsquo;ll also note Kudos / Gratitude to Unhook for making a YouTube-management Chrome extension that I&amp;rsquo;ve started using as well.&lt;/p&gt;
&lt;p&gt;Good browsing and good night!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Strategic Life Thinking</title>
      <link>https://davidbieber.com/snippets/2024-01-06-strategic-life-thinking/</link>
      <pubDate>Sat, 06 Jan 2024 03:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2024-01-06-strategic-life-thinking/</guid>
      
      <description>&lt;p&gt;I stumbled on this 
&lt;a href=&#34;https://www.youtube.com/watch?v=dbiNhAZlXZk&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;YouTube video&lt;/a&gt; today called &amp;ldquo;Use Strategic Thinking to Create the Life You Want&amp;rdquo; and surprised myself by enjoying the video. Among other things, it suggested plotting out sixteen different aspects of your life according to how important they are to you, and how satisfied you are with them. Once you&amp;rsquo;ve done that, you can use this plot to start thinking about any adjustments you might want to make in your behaviors.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Gee, with ChatGPT I could probably throw together a widget for this exercise in under half an hour,&amp;rdquo; I thought to myself. Its the sort of prediction you might expect to be a dramatic underestimate. Not this time though. Here&amp;rsquo;s the finished product with instructions below:&lt;/p&gt;
&lt;link href=&#34;https://davidbieber.com/snippets/2024-01-06-strategic-life-thinking/app/static/css/main.e9bd4978.css&#34; rel=&#34;stylesheet&#34;&gt;
&lt;script defer=&#34;defer&#34; src=&#34;https://davidbieber.com/snippets/2024-01-06-strategic-life-thinking/app/static/js/main.4f983d6d.js&#34;&gt;&lt;/script&gt;
&lt;noscript&gt;You need to enable JavaScript to run this app.&lt;/noscript&gt;
&lt;div id=&#34;root&#34;&gt;&lt;/div&gt;
&lt;br/&gt;
&lt;p&gt;The exercise is to rate the importance of each of these sixteen areas on a scale from 0-10, and to rate how satisfied you are with each area also on a scale from 0-10. The widget will automatically plot the areas as you&amp;rsquo;re rating them. You can also click and drag the circles around, if you&amp;rsquo;d prefer to rate the areas that way.&lt;/p&gt;
&lt;p&gt;Want to work on community, societal engagement, or friendship? Send me a screenshot of your final plot ;).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Say What You Think</title>
      <link>https://davidbieber.com/snippets/2023-12-02-say-what-you-think/</link>
      <pubDate>Sat, 09 Dec 2023 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2023-12-02-say-what-you-think/</guid>
      
      <description>&lt;p&gt;Today&amp;rsquo;s topic is the SWYT in 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-01-02-pyd-swyt-cf-bh-din/&#34;&gt;pyd-swyt; cf-bh-din&lt;/a&gt;: say what you think.
We&amp;rsquo;ve already covered what it means to me to 
&lt;a href=&#34;https://davidbieber.com/snippets/2022-01-11-pursuing-your-dreams/&#34;&gt;BH (&amp;ldquo;be happy&amp;rdquo;)&lt;/a&gt; and to 
&lt;a href=&#34;https://davidbieber.com/snippets/2023-07-31-pursue-your-dreams/&#34;&gt;PYD (&amp;ldquo;pursue your dreams&amp;rdquo;)&lt;/a&gt;. Today we dive into SWYTing &amp;ndash; saying what you think.&lt;/p&gt;
&lt;p&gt;This is easily the toughest one for me.
I often self-censor. So, I&amp;rsquo;m going to start this exploration with a quick brainstorming of why this might be. Expand the text below to see the full brainstorm. I include my complete initial thoughts here, though upon review I think the actual explanations behind some of these &amp;ldquo;System 1 rationales&amp;rdquo; differ from the System 1 rationales themselves in a handful of instances. We can dive into that more after.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Expand this to see the full brainstorming.&lt;/summary&gt;
&lt;pre&gt;
- Love / expectations of the other person
- Concern for how something will be received
- Whether it would make someone uncomfortable
- Whether it would... yeah, make them uncomfortable or be hurtful or be rude
- Reshaping things to say the same thing but in a kinder less violent way takes time
- But this is something that I can get faster at with practice
&lt;/pre&gt;
&lt;pre&gt;
Other reasons for not saying what I want to include:
- Concern about putting things on the permanent record; let&#39;s explore that one in more depth
- Concern about creating additional comms overhead (having to deal with replies, requests, disagreements, etc)
    - Even if ignoring and not responding to these, they still come with significant mental overhead.
- Concerns about confidentiality also stifle my saying what I think in a couple ways:
    - One is confidentiality for my employer
    - If something is a secret then I don&#39;t want to share it publicly
    - Especially since the merger this has been uncomfortable since so much is NTK now
    - And then on a more personal level, there are lots of things that I&#39;d love to discuss that feel like they aren&#39;t mine to tell
    - They might involve saying something that could be perceived as negative about another person, or they might involve something that could be considered private by another person
        - (This could either be something intimate, or something they might not be ready to share like an idea they&#39;re working on in stealth, etc.)
        - Or maybe it just feels like it&#39;s their story, and they might want to tell it themselves on their own time.
&lt;/pre&gt;
&lt;pre&gt;
- Another thing that can hold back my saying what I think is private-seeming things; things that are more emotional or intimate don&#39;t necessarily feel appropriate to share in most contexts.
    - Mental health coaching has been great.
    - It&#39;s created an atmosphere in which sharing is the default and so my inhibitions around sharing are dropped substantially there.
- Journalling on Go Note Go has also done wonders for dropping inhibitions toward writing.
    - And the snippets section of my website -- [writing for no audience](/snippets/2019-12-30-writing-for-no-audience/) -- has done wonders too.
- Oh, I&#39;m reminded of yet another source of inhibition:
    - A fear of looking stupid (or, to use less judgemental language: a fear of revealing gaps in my knowledge and skillsets.)
    - I&#39;m pretty good at not succumbing to this inhibition, but it&#39;s certainly there alongside all the rest.
&lt;/pre&gt;
&lt;pre&gt;
- So, I&#39;ve given a rather lengthy list of forces working against my desire to say what I think.
- And there are still more perhaps:
    - I&#39;ll reiterate the aversion to making others feel uncomfortable.
    - Conflict avoidance is another.
    - A natural inclination toward trying to help with what I perceive to be others&#39; desires (including e.g. making space if I think someone doesn&#39;t want to talk to me :()
    - I might even have a length penalty, a bias against droning on, leading to compact speech that might lack important context or information.
    - And finally I&#39;ll add a note about vulnerability, which I think is what I was alluding to when I started out the brainstorming with the word &#34;Love&#34;.
&lt;/pre&gt;
And finally some addendums:
&lt;pre&gt;
One I did not mention is thinking before speaking; Let&#39;s add that to the list.
Let&#39;s also add the difficulties (1) of knowing what I want to say and (2) of actually saying it.
And avoiding seeming petty or overly critical.
Rereading while writing (aka perfectionism or overthinking the details) can impede thinking about the high level / can be a form of self-censorship.
&lt;/pre&gt;
&lt;/details&gt;
&lt;br/&gt;
&lt;p&gt;The reasons I discovered for not saying what I think were more numerous than I expected!&lt;/p&gt;
&lt;p&gt;They included:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Avoiding vulnerability&lt;/li&gt;
&lt;li&gt;An automatic draw towards meeting expectations&lt;/li&gt;
&lt;li&gt;Conflict avoidance&lt;/li&gt;
&lt;li&gt;Avoiding making other people uncomfortable&lt;/li&gt;
&lt;li&gt;A fear of permanence&lt;/li&gt;
&lt;li&gt;A fear of consequences&lt;/li&gt;
&lt;li&gt;An aversion to creating a communications overhead&lt;/li&gt;
&lt;li&gt;Respecting confidentiality&lt;/li&gt;
&lt;li&gt;Trying to be helpful&lt;/li&gt;
&lt;li&gt;A natural inclination toward brevity&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Right. So now that we&amp;rsquo;ve run through so many reasons that my brain produces against saying what I think, I must reiterate that I hold &lt;em&gt;saying what I think&lt;/em&gt; among the five most important things for me to do in life. (The five of course being 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-01-02-pyd-swyt-cf-bh-din/&#34;&gt;pyd-swyt; cf-bh-din&lt;/a&gt; (Pursue your dreams, say what you think, cultivate friendships, be happy, do it now.)&lt;/p&gt;
&lt;p&gt;So it would behoove me to think explicitly about the value of saying what you think.
And maybe to think more critically about each of the reasons against.&lt;/p&gt;
&lt;p&gt;Some of the reasons my brain gives against are legitimate reasons, so while I do want to knock them down a peg, I also want to take them seriously and give them due consideration.&lt;/p&gt;
&lt;p&gt;First, I will write about why I want to say what I think, and why I value this enough to include it in my pyd-swyt; cf-bh-din guiding mantra. Then, after, we can return to the negatives / to the brainstormings above and think critically about them. So, let&amp;rsquo;s begin with the benefits.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;As with the negatives above, I start with a brainstorming; click to expand it.&lt;/summary&gt;
&lt;pre&gt;
There are so many reasons to say what you think. What are they?
First major category is that then people know what you think!
They can&#39;t give you want you want or respect your preferences or stop doing annoying things that bother you
  if they don&#39;t know what you want, what your preferences are, or that they&#39;re doing an annoying thing that bothers you.
It can be easy to assume that people know these things about you.
But even when someone does know these things about you, they might not be top of mind.
Saying these things explicitly therefore serves at least two purposes:
(1) conveying the information, and
(2) bringing the information to the forefront of the other person&#39;s mind.
&lt;/pre&gt;
&lt;pre&gt;
This brings us to benefit of saying what you think number (3):
  saying what you think helps you clarify what you think.
If you&#39;re merely thinking the thing, then it can remain a fuzzy neural idea.
Saying it forces you to concretize it into words, and words that make sense to other human beings to boot!
This is standard advice about writing: by forcing you to articulate your ideas they become more precise.
The same is true for conversation too.
And not only do the ideas get better through the internal processes of formulation for speech and articulation itself,
you get benefit number (4):
  other people think about what you&#39;ve said.
&lt;/pre&gt;
&lt;pre&gt;
Really hard to overstate the value of number (4).
One way to frame it is that you&#39;re putting other people&#39;s computation to work on your own problems.
I guess I&#39;m writing as a software engineer now.
It&#39;s parallelization!
By saying what you think to someone else, you might immediately double the processing power being devoted to the idea expressed.
Give a talk to a group of ten, and you&#39;re now using human processing power unobtainable even in a week&#39;s timeframe if working alone. Wild!
A less computation-centric way to frame this is that you get feedback from others.
That&#39;s really valuable for honing your ideas, deciding on future directions, finding collaborators, figuring out what makes others tick, etc.
&lt;/pre&gt;
&lt;pre&gt;
To recap we&#39;ve already uncovered a trove of benefits to SWYT:
* communicating information
* people can know/meet/actively-consider your needs/wants/etc
* clarify your own thinking
* getting other people&#39;s insights.
But there&#39;s so much more! Let&#39;s brainstorm onward.
&lt;/pre&gt;
&lt;pre&gt;
* Practice: By saying what you think, you get better at saying what you think! This means you can get all those other benefits we&#39;ve listed out more readily.
* Storytelling, forming connection with others, getting to know one another and learning new things. Being vulnerable and opening up might be difficult and scary at first, but can be rewarding too!
* Not implicitly projecting agreement through silence.
* Inspiring others
* Earning people&#39;s respect and trust
* Shaping the focus and attention of the audience and their circles
* Feeling connection, staving off loneliness
* Cheering someone up, expressing gratitude
&lt;/pre&gt;
&lt;pre&gt;
I worry the brainstorm might have broadened too much;
  there sure are a lot of reasons to *communicate*,
but I&#39;m specifically interested in reasons for saying what you think when it might otherwise be difficult.
There are times when I might naturally choose not to say what I think and instead stay quiet
(or worse, implicitly suggest something opposed with what I actually think, e.g. to avoid conflict!).
My goal with this brainstorm is to enumerate the reasons in favor of saying what I think in these situations.
&lt;/pre&gt;
&lt;pre&gt;
* Honesty; staying true to myself
* Not being a pushover, not conceding ground simply because someone else is louder or more confident
* Promoting intellectual discussions, and an honest battle of ideas
&lt;/pre&gt;
&lt;pre&gt;
I think I can sometimes assume people see things the same way I do even when that is not actually the case,
  e.g. because I assume my own belief is an obvious one.
But I&#39;ve learned since that when someone says they disagree, they generally actually do.
They aren&#39;t usually being silly or joking or sarcastic. And so it can be valuable to explore that disagreement.
&lt;/pre&gt;
&lt;pre&gt;
* Avoiding being misleading (see &#34;Not implicitly projecting agreement through silence&#34;; perhaps this is a generalization of that.) E.g. it can include not seeming like you&#39;re agreeing to do something when you actually don&#39;t intend to do it.
* In the case of expressing a preference about someone&#39;s behavior, it can be tempting not to say what you think because the situation seemingly has already passed.
But saying what you think can prevent future situations that bother you in the same way from coming about again.
&lt;-- This brings up a reason against saying what you think that I didn&#39;t think of in the first brainstorm: avoiding seeming petty or overly critical. I&#39;ll go up and add that there now.
&lt;/pre&gt;
&lt;p&gt;Solid brainstorm! Moving on.&lt;br/&gt;
Well, not quite yet. After some additional writing, I resumed brainstorming mode for a moment longer:&lt;/p&gt;
&lt;pre&gt;
* Getting my needs met?&#39;
  (I never did understand the idea of &#34;needs&#34;. Update: I&#39;ve learned the term universal motivators and may prefer that.)
* Letting people know what I&#39;m thinking about
  -&gt; Then people can share related ideas, introduce me to people who might be thinking about or working on related things, invite me to things I might enjoy
Can also establish connection between me and the other person.
It also makes it so much easier for people to respect my preferences if they know what they are.
(And doubly so if they&#39;re top of mind; a preference known but not present in the attention is little better than a preference unknown at all.)

I&#39;ve oft had an aversion to the notion of &#34;the squeaky wheel gets the grease&#34;, especially in situations when the grease is something evenly desirable to all wheels. What if a wheel isn&#39;t being squeaky out of respect for the needs of the other wheels, and for a belief in the fairness of the grease distributor? This was my thinking, but I&#39;m slowly moving away from this as I realize the truth of this aphorism might be out of our control. I don&#39;t know. On the one hand, we could teach all the wheels to be squeaky, and that would resolve the fairness concerns. But there is a long tail of wheels, and surely some wheels needing grease or other attention simply won&#39;t squeak. And all that extra squeaking doesn&#39;t sound super desirable to begin with.
Perhaps far better than teaching the wheels to squeak is to teach them what we can about the grease distributor. Then if beliefs in the fairness of the grease distributor are unsound, perhaps such beliefs won&#39;t develop as readily.
&lt;/pre&gt;
&lt;p&gt;Okay, that concludes the brainstorming.&lt;/p&gt;
&lt;/details&gt;
&lt;br/&gt;
&lt;p&gt;From that brainstorm I identified quite a host of benefits to saying what I think. Let&amp;rsquo;s recap with a list, and then expand on a few of them.&lt;/p&gt;
&lt;p&gt;The list of benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Communicating information&lt;/li&gt;
&lt;li&gt;People can know/meet/actively-consider your needs/wants/motives&lt;/li&gt;
&lt;li&gt;Clarify your own thinking&lt;/li&gt;
&lt;li&gt;Get feedback or thoughts from others&lt;/li&gt;
&lt;li&gt;Practice saying what you think so you&amp;rsquo;re better at it later&lt;/li&gt;
&lt;li&gt;Connect with others, for yourself and for the others&lt;/li&gt;
&lt;li&gt;Avoid implicitly agreeing -&amp;gt; stay honest and true to yourself&lt;/li&gt;
&lt;li&gt;Inspire others; shape the dialog!&lt;/li&gt;
&lt;li&gt;Learn something new and promote dialog&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Practice.&lt;/strong&gt; Let&amp;rsquo;s start off with a bit of a self-referential one. In combination with all the others, it ends up being quite important. Saying what I think now is key for making it easier to say what I think later. I.e. saying what I think when it is less important or less pressing (e.g. a dinner preference) might set me up well to say what I think in a hospital at some point, or in a courtroom, or a meeting with an executive etc. There are all these situations where the ability to stand up for one&amp;rsquo;s beliefs and to do so in a timely efficient manner is really important. And saying what you think &lt;em&gt;every day&lt;/em&gt; is a key step toward being able to say what you think when it really matters.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Not implicitly projecting agreement through silence.&lt;/strong&gt; I&amp;rsquo;ve had a few situations recently where someone has expressed an interest in working together, and I don&amp;rsquo;t explicitly say no, but I don&amp;rsquo;t say yes either, and while I say something indicative of hesitation, the other party seems to assume I&amp;rsquo;ve said yes. Similarly, I&amp;rsquo;ve had situations where someone expresses an idea, and I disagree, but I nod along so as to hear the rest of the idea and better understand it; this has also been mistaken for agreement as well. I&amp;rsquo;d love to project an accurate reflection of my beliefs, and this all starts with saying what I think.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Getting insights from others.&lt;/strong&gt; This can be the most satisfying one because it is by definition surprising.
When you get others&#39; thoughts on your ideas, you obtain new information, stuff you hadn&amp;rsquo;t thought of. Perhaps ideas you didn&amp;rsquo;t even know you weren&amp;rsquo;t considering! What a beautiful gift! If you&amp;rsquo;re like me, and find yourself subconsciously falling prey to the 
&lt;a href=&#34;https://davidbieber.com/snippets/2022-01-07-efficient-minds-fallacy/&#34;&gt;Efficient Minds Fallacy&lt;/a&gt;, this is a key benefit to remind yourself of. (I say &amp;ldquo;you&amp;rdquo; a lot, but I&amp;rsquo;m clearly writing all this for myself&amp;hellip;)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Getting your needs met.&lt;/strong&gt; I think this is probably the most important one. The important kind of SWYTing that I want to encourage in myself is stating my boundaries clearly, expressing my emotions and opinions, and both knowing and expressing my preferences with confidence (all while remaining easy-going!). When a weakly-held (though possibly important) preference meets gentle conflict avoidance, by default the conflict avoidance can win out; this is where the SWYT mantra is critical!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Clarifying your thinking.&lt;/strong&gt; Of course saying what you think is a great way to develop your thoughts. That&amp;rsquo;s one of the reasons I write these snippets! It&amp;rsquo;s eye-opening how, while this benefit is tremendous and is a critical reason to SWYT, it feels like it pales in comparison to the previous one: getting your needs met. Perhaps that&amp;rsquo;s because using SWYT to clarify my thinking is (comparatively) easy for me; e.g. I&amp;rsquo;ve been writing these snippets for three years now. Using SWYT in the face of conflict avoidance, on the other hand, is a challenge where having the SWYT mantra is really important for me. Nevertheless, the benefits of using SWYT to clarify my thinking both myself, as well as through the feedback and insights of those I share with, is a welcome reason to practice SWYT. I hope that by practicing SWYT here, I can become more comfortable with it in the more challenging situations where it arises.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;We&amp;rsquo;ve identified about ten reasons against saying what you think, and about ten reasons in favor as well.
Since SWYT is part of 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-01-02-pyd-swyt-cf-bh-din/&#34;&gt;pyd-swyt; cf-bh-din&lt;/a&gt;, you already know that I believe the benefits outweigh the reasons against pretty heavily.
But believing that consciously is not the same as living it, and there are still plenty of situations where SWYT is a challenge for me.
Primarily, the challenge arises when the SWYT principle butts heads with conflict avoidance, and I shirk from stating a preference. I hope that through the process of this reflection, as well as through practicing SWYT in both the easy and challenging situations, the challenging situations get ever easier to SWYT.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Food Preferences</title>
      <link>https://davidbieber.com/snippets/2023-09-17-food-preferences/</link>
      <pubDate>Sun, 17 Sep 2023 20:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2023-09-17-food-preferences/</guid>
      
      <description>&lt;p&gt;Here are my food preferences, all typed up nice and neat in a way that Bard or ChatGPT can easily digest. Now when I travel somewhere, I can ask these LLMs to help me pick out restaurants well suited to my tastes!&lt;/p&gt;
&lt;h3 id=&#34;as-written-by-a-human&#34;&gt;As written by a human&lt;/h3&gt;
&lt;p&gt;🥗 I really enjoy tomato based sauces.&lt;br/&gt;
🥗 Some particularly wonderful foods I enjoy include chicken parm, chicken tikka masala, drunken noodles.&lt;br/&gt;
🥗 I enjoy eating at restaurants where they make foods that I wouldn&amp;rsquo;t easily be able to make myself.&lt;br/&gt;
🥗 I don&amp;rsquo;t want to eat novel foods for the sake of it (e.g. I don&amp;rsquo;t want to try silly new flavors of ice cream), but if there are foods I&amp;rsquo;m unfamiliar with that are core to certain cuisines, then I&amp;rsquo;m definitely curious and interested in trying those. A recent example is I discovered uni.&lt;br/&gt;
🥗 I like very flavorful food. One of my favorite meals ever is from Damas, a Syrian restaurant in Montreal.&lt;br/&gt;
🥗 I don&amp;rsquo;t have any dietary restrictions, but I do like to eat more veggies and less meat. I tend to enjoy vegan restaurants, even though I also like all sorts of meat dishes too.&lt;br/&gt;
🥗 I like mushroom-based foods, like a good mushroom based turkey meatloaf.&lt;br/&gt;
🥗 I think food tastes better when I&amp;rsquo;m hungry, e.g. after a long hike or swim.&lt;br/&gt;
🥗 I like pizza, pasta, ravioli, thai food.&lt;br/&gt;
🥗 I only like spicy food in moderation; I don&amp;rsquo;t want spice in every meal I eat, but I do like to eat spicy food here and there, and I have a decent spice tolerance and appreciation when I do.&lt;br/&gt;
🥗 I prefer savory food over sweet food usually, sometimes opting for a second dinner over a dessert. I do like a good sweet dessert though, but usually in a smaller quantity compared with the large quantities I enjoy for other foods.&lt;br/&gt;
🥗 I don&amp;rsquo;t have any food allergies.&lt;br/&gt;
🥗 I like seafood, e.g. salmon, crab, scallops, and uni. Calamari is a delight too.&lt;br/&gt;
🥗 I enjoy Italian, Mexican, Thai, and Indian food. I can&amp;rsquo;t think of a cuisine I don&amp;rsquo;t like, really. Maybe I have a slight preference against cuisines that are super meat-heavy, but even that can be enjoyable for me every once in a while.&lt;br/&gt;
🥗 I enjoy cooking, both trying new things as well as preparing old staples for myself. For trying new things, that&amp;rsquo;s something I like to do but only every now and then. For regular everyday cooking, I prefer quicker dishes without recipes: e.g. making a salad, a grain, and a protein, maybe with a pan sauce &amp;ndash; usually a full meal can come together in under 30 minutes.&lt;br/&gt;
🥗 Fresh produce is wonderful! I don&amp;rsquo;t mind processed or fast food in moderation, but for me healthier fresher foods are the way to go! I also don&amp;rsquo;t really drink soda&amp;hellip; or much of anything other than water usually, to be honest.&lt;br/&gt;
🥗 Kimchi is enjoyable for me in moderation, same with other fermented foods like sauerkraut &amp;ndash; but usually I&amp;rsquo;d eat them only in the context of a meal where they fit in. I&amp;rsquo;m not a big fan of kombucha.&lt;br/&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Finally, I had an AI take a pass at tidying up the preferences, which I present below, but I&amp;rsquo;m actually more partial toward my original human-authored attempt.&lt;/p&gt;
&lt;h3 id=&#34;flavor-profile-preferences&#34;&gt;Flavor Profile Preferences&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Balanced and Wholesome:&lt;/em&gt; You have a fondness for foundational foods that offer a harmonious blend of flavors, like salads with olive oil and balsamic or bread paired with garlic and olive oil. These are neither too overpowering nor too subtle and give a sense of nourishment.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Adventurous but Authentic:&lt;/em&gt; You lean towards dishes that offer genuine tastes of their cultural origins. Whether it’s Middle Eastern hummus and shawarma or Asian specialties like pad Thai, you seek the authenticity in flavors. This shows an appreciation for the traditional essence of dishes.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Occasional Boldness:&lt;/em&gt; While you&amp;rsquo;re open to spicy foods and rich BBQ flavors, these are more of occasional delights rather than daily go-tos. This indicates a palate that can handle and enjoy robust flavors but prefers them in moderation.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Natural and Fresh:&lt;/em&gt; With a preference for fresh produce and a lean towards plant-based options, you value the intrinsic flavors of fresh ingredients. This showcases an inclination towards natural, unadulterated tastes, aligning with your philosophy of healthier, fresher foods.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Savory over Sweet:&lt;/em&gt; Your palate seems to lean more towards the savory, often even opting for a second dinner over a dessert. However, you do have a space for sweet treats, albeit in controlled portions, showing a versatile yet controlled taste preference.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Subtle Indulgences:&lt;/em&gt; Whether it’s a creamy cheese, a delightful seafood dish, or a special dessert, you appreciate the finer tastes in life without them dominating your daily food choices.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Hydration Purist:&lt;/em&gt; With water being your primary beverage, it’s evident that you prefer clean, refreshing tastes in your drinks, staying away from overly sugary or artificial flavors.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Violin Tuner Experiment</title>
      <link>https://davidbieber.com/snippets/2023-09-17-violin-tuner/</link>
      <pubDate>Sun, 17 Sep 2023 03:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2023-09-17-violin-tuner/</guid>
      
      <description>&lt;p&gt;This is an interactive little page. If you have a violin handy, go ahead and play a note or two, and watch the finger diagrams change. If you don&amp;rsquo;t have a violin on you, you can try singing instead. Scroll down for details about what&amp;rsquo;s going on here.&lt;/p&gt;
&lt;script defer=&#34;defer&#34; src=&#34;https://davidbieber.com/snippets/2023-09-17-violin-tuner/app/static/js/main.7306df6c.js&#34;&gt;&lt;/script&gt;
&lt;p&gt;&lt;noscript&gt;You need to enable JavaScript to run this app.&lt;/noscript&gt;&lt;/p&gt;
&lt;div id=&#34;root&#34;&gt;&lt;/div&gt;
&lt;h3 id=&#34;what-is-this&#34;&gt;What is this?&lt;/h3&gt;
&lt;p&gt;Each diagram shows the violin finger positions for a different scale. When you play a note, the page shows the pitch you&amp;rsquo;re playing as a magenta line. The closest note will be highlighted in dark blue. If the note precisely goes through the center of the circle, it&amp;rsquo;s in tune.&lt;/p&gt;
&lt;p&gt;These twenty-four diagrams above show the notes accessible in first position on the violin in each of the major and minor scales. Consider each diagram in isolation. The note highlighted in light blue is the root note of the scale. The finger positions for all the notes in the scale are labeled.&lt;/p&gt;
&lt;p&gt;To use this page as a tuner, try to make the magenta line precisely line up with the centers of the circles. The scales I&amp;rsquo;m practicing are highlighted in blue.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Musical Aspirations</title>
      <link>https://davidbieber.com/snippets/2023-09-17-musical-aspirations/</link>
      <pubDate>Sun, 17 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2023-09-17-musical-aspirations/</guid>
      
      <description>&lt;p&gt;In 2017 I picked up violin again, after a 15 year hiatus. I&amp;rsquo;d played throughout fourth grade, but then put the instrument down to focus on my studies.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m now plodding away at learning guitar and violin, and playing bits on the keyboard. It would be good to have some goals so I can direct my studies. One candidate goal based on my recent playing would be to produce You&amp;rsquo;ve Got a Friend in Me on all of these instruments: piano, violin, guitar, and I could even do vocals. I could record each of these separately and put them together in Ableton.&lt;/p&gt;
&lt;p&gt;Playing this on piano and violin seems well within reach. However, the number of new chords and speed of switching required to play it on guitar (at least from the arrangement I&amp;rsquo;ve seen so far) doesn&amp;rsquo;t feel super within reach right now. And as for the vocals&amp;hellip; well, I can at least get the words out, even if not the notes.&lt;/p&gt;
&lt;p&gt;Returning to the last time I thought about musical goals, I had some smaller ambitions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On piano, I wanted to be able to play all the scales&lt;/li&gt;
&lt;li&gt;On violin, You&amp;rsquo;ve Got a Friend in Me&lt;/li&gt;
&lt;li&gt;And I hadn&amp;rsquo;t even started guitar yet..&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ah, I&amp;rsquo;ve just checked and I&amp;rsquo;d misremembered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My violin goal from Dec 3 2022 was to play scales in every key.&lt;/li&gt;
&lt;li&gt;My piano goal was also to play scales in every key.&lt;/li&gt;
&lt;li&gt;And my guitar goal was to play the chords in House of the Rising Sun.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think these goals still seem like proper first goals. So, by putting them in a snippet, perhaps I will encourage myself to pursue them more quickly. Then I can get to my You&amp;rsquo;ve Got a Friend In Me goals sooner.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Aside: is that an instance of double sarcasm? I will have to dedicate a full snippet to double sarcasm at some point. In this instance, it&amp;rsquo;s meant to be a joke, but also might literaly be true&amp;hellip; Maybe not sarcasm but something in that vein. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Pursue Your Dreams</title>
      <link>https://davidbieber.com/snippets/2023-07-31-pursue-your-dreams/</link>
      <pubDate>Mon, 31 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2023-07-31-pursue-your-dreams/</guid>
      
      <description>&lt;p&gt;
&lt;a href=&#34;https://davidbieber.com/snippets/2020-01-02-pyd-swyt-cf-bh-din/&#34;&gt;pyd-swyt; cf-bh-din&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve written about 
&lt;a href=&#34;https://davidbieber.com/snippets/2022-01-11-pursuing-your-dreams&#34;&gt;pyd (pursuing your dreams)&lt;/a&gt; before. Or at least I&amp;rsquo;ve tried; I think it came out as being more about bh (being happy).&lt;/p&gt;
&lt;p&gt;So, today, in this snippet, I will try once more to explore the idea of pursuing my dreams. What does it mean to me to pursue my dreams?&lt;/p&gt;
&lt;p&gt;Rereading 
&lt;a href=&#34;https://davidbieber.com/snippets/2022-01-11-pursuing-your-dreams&#34;&gt;the existing pyd snippet&lt;/a&gt;, everything in there still rings true. I think it&amp;rsquo;s a fabulous description of what makes me happy. I was initially embarassed by it, but I&amp;rsquo;ve come to like it over time. However, my dreams go beyond my happiness. Let&amp;rsquo;s explore that.&lt;/p&gt;
&lt;p&gt;I dream of a future where people can do a full day&amp;rsquo;s software engineer work without looking at a screen. In this future, people are more in control of their own attention.&lt;/p&gt;
&lt;p&gt;I dream of a world where my family and friends (and theirs as well, etc!) can live healthy happy lives for a thousand years. In this world, our memories are robust and precious.&lt;/p&gt;
&lt;p&gt;I dream that I can take the music in my head and bring it into the world. That the music in my head be sound (and that the sounds in my head be music!).&lt;/p&gt;
&lt;p&gt;I dream of growing a family that I love and treasure with a woman I love. Of enjoying this ride with them until I am very old.&lt;/p&gt;
&lt;p&gt;I dream of being part of a rich community of people who are often eager to collaborate to bring our silly side projects to life. We take our silly ideas seriously.&lt;/p&gt;
&lt;p&gt;I dream of learning meaningfully from my peers (and vice versa) all throughout my life. May there never be a shortage of known unknowns.&lt;/p&gt;
&lt;p&gt;I dream of a thousand snowfalls and ten thousand sunrises, all around the world.&lt;/p&gt;
&lt;p&gt;I dream that access to life&amp;rsquo;s basic needs, food, water, shelter, love and affection, internet access, a quality education, books, and friendship are so taken for granted that&amp;hellip; new levels of our hierarchy of needs become recognized as the base 🤷. I dream of a world where everyone feels truly heard.&lt;/p&gt;
&lt;p&gt;I dream of experiencing the feeling of learning to program for the first time not just once more, but over and over again (and not because I forget how to program!).&lt;/p&gt;
&lt;p&gt;These are good. Let&amp;rsquo;s keep brainstorming. We can whittle away at them into something more pithy later. So far these dreams center around technological progress (screenless tech, longevity, meeting people&amp;rsquo;s needs), personal growth (the music one, peer learning, the feeling of learning to program), connection (longevity, growing a family, the collaborative community, everyone feeling heard), adventure (snowfalls and sunrises, growing a family). Most of the dreams are me-centric, whereas only a couple are substantially altruistic (longevity and meeting people&amp;rsquo;s needs). As I continue to ponder my dreams, I might think more along the lines of altruism; I might also think further around what skills and experiences I want, what legacy I wish to leave, or how I want to live my life.&lt;/p&gt;
&lt;p&gt;Then, the next aspect of this I wish to write about is how to actively pursue my dreams. The first step of course is identifying them. And I&amp;rsquo;ve now begun that step. But pursuing them is required for pyd, and that is where the real adventure begins.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What&#39;s alive in you?</title>
      <link>https://davidbieber.com/snippets/2023-07-02-alive-in-you/</link>
      <pubDate>Sun, 02 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2023-07-02-alive-in-you/</guid>
      
      <description>&lt;p&gt;Greetings! How are you today? How do you like to ask that question? One option is &amp;ldquo;what&amp;rsquo;s alive in you?&amp;rdquo;.&lt;/p&gt;
&lt;h3 id=&#34;the-alternatives&#34;&gt;The alternatives&lt;/h3&gt;
&lt;p&gt;I have a couple of people in my life who ask this question: &amp;ldquo;what&amp;rsquo;s alive in you?&amp;rdquo;.
Aside from the slight downside of elliciting funny looks, I think it&amp;rsquo;s a solid alternative to &amp;ldquo;how are you?&amp;rdquo; as a conversation opener when you are looking to have a meaningful conversation.
Of course, often &amp;ldquo;how are you?&amp;rdquo; is &lt;em&gt;not&lt;/em&gt; intended to introduce a meaningful undirected conversation; it gets used as a pleasantry too, with the actual direction for the conversation to be provided shortly later (as in the opening line to this snippet).&lt;/p&gt;
&lt;h3 id=&#34;the-abiguity-present-in-how-are-you&#34;&gt;The abiguity present in &amp;ldquo;how are you?&amp;rdquo;&lt;/h3&gt;
&lt;p&gt;So there&amp;rsquo;s an ambiguity in receiving the phrase &amp;ldquo;how are you?&amp;rdquo; which I think dampens its utility as a question, despite it&amp;rsquo;s popularity.
On the one hand, you can reply to &amp;ldquo;how are you?&amp;rdquo; with a simple evaluation (e.g. &amp;ldquo;good&amp;rdquo;), for which it is even often socially acceptable to lie if the answer is less than &amp;ldquo;fine&amp;rdquo; but you don&amp;rsquo;t want to get into it. The other common way to reply is to provide a piece of evidence &amp;ndash; a thing from your life that relates to how you&amp;rsquo;re doing, whether that be a thing you did recently or a thing coming up in the future.
Each of these replies is fine, with the later opening the conversation up a bit more or giving it a bit more direction.&lt;/p&gt;
&lt;h3 id=&#34;what-whats-alive-in-you-conveys&#34;&gt;What &amp;ldquo;what&amp;rsquo;s alive in you?&amp;rdquo; conveys&lt;/h3&gt;
&lt;p&gt;&amp;ldquo;What&amp;rsquo;s alive in you?&amp;rdquo; differs from &amp;ldquo;how are you?&amp;rdquo; in two key regards. It asks something slightly different, and it conveys a different level of interest in the response.
&amp;ldquo;What&amp;rsquo;s alive in you?&amp;rdquo; asks what feels most salient, what occupies our thoughts and attention.
It&amp;rsquo;s not about absolute history from the world&amp;rsquo;s perspective &amp;ndash; the things that happened around us, or the events that took place where we were present &amp;ndash; though certainly these things will deeply shape our thoughts and attention. And though &amp;ldquo;how are you?&amp;rdquo; invites similar responses too, &amp;ldquo;what&amp;rsquo;s alive in you?&amp;rdquo; makes clear that a deeper response is welcome in a way that &amp;ldquo;how are you?&amp;rdquo; does not.&lt;/p&gt;
&lt;h3 id=&#34;the-role-of-memory-in-how-was-your-day-vs-whats-alive-in-you&#34;&gt;The role of memory in &amp;ldquo;how was your day?&amp;rdquo; vs &amp;ldquo;what&amp;rsquo;s alive in you?&amp;rdquo;&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve been in several situations where the questions &amp;ldquo;how was your day?&amp;rdquo; or &amp;ldquo;how was your weekend?&amp;rdquo; are greeted with silence while the questionee tries to recall the notable events from their day or weekend. These questions are implicitly requesting some memory seeking.
By contrast, &amp;ldquo;What&amp;rsquo;s alive in you?&amp;rdquo; requires no activation of the memory. It does require some amount of introspection, but that introspection is about the present. The goal in taking the question seriously is to identify the things already present in the attention (not literally limited to the present attention; this can certainly include recent attention as well), rather than things we could have been attending to or reflecting on.&lt;/p&gt;
&lt;h3 id=&#34;the-what-have-you-been-thinking-about-alternative&#34;&gt;The &amp;ldquo;what have you been thinking about?&amp;rdquo; alternative&lt;/h3&gt;
&lt;p&gt;In this regard, I also like the questions &amp;ldquo;what have you been thinking about lately?&amp;quot;; this doesn&amp;rsquo;t lean on metaphor as much as &amp;ldquo;what&amp;rsquo;s alive in you?&amp;rdquo; and as a result is understood more quickly and with fewer funny looks than the &amp;ldquo;what&amp;rsquo;s alive in you?&amp;rdquo; query. Responses to &amp;ldquo;what have you been thinking about lately?&amp;rdquo; may skew a bit more academic though, whereas &amp;ldquo;what&amp;rsquo;s alive in you?&amp;rdquo; skews more personal.&lt;/p&gt;
&lt;h3 id=&#34;maybe-my-snippets-are-little-bits-of-whats-alive-in-me&#34;&gt;Maybe my snippets are little bits of what&amp;rsquo;s alive in me&lt;/h3&gt;
&lt;p&gt;In some ways, my 
&lt;a href=&#34;https://davidbieber.com/snippets&#34;&gt;snippets system&lt;/a&gt; is about answering the question &amp;ldquo;what&amp;rsquo;s alive in me?&amp;rdquo; for myself.
With this particular snippet, my main goal was simply to get any snippet at all published, since it&amp;rsquo;s been a few months since I&amp;rsquo;ve put a snippet out.
I want to reactivate the habit of snippet writing. As I&amp;rsquo;ve seen before, a solid way for me to do this is to publish &amp;ldquo;deliberate drivel&amp;rdquo; (or at least content where there is no quality bar to publication) to help make it mentally easier for me to keep sharing thoughts in snippets.&lt;/p&gt;
&lt;h3 id=&#34;snippet-reactivation-brainstorming&#34;&gt;Snippet reactivation brainstorming&lt;/h3&gt;
&lt;p&gt;Since this is a &amp;ldquo;reactivation snippet&amp;rdquo;, I&amp;rsquo;ll take a moment to brainstorm some of the things I could write about in future posts or snippets.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reflections on AI in daily life&lt;/li&gt;
&lt;li&gt;Healthy habits: meditation, yoga, sleep, healthy eating, violin, reading, writing, hosting, HIIT, Tabata, stretch therapy, floating, mental health, NVC&lt;/li&gt;
&lt;li&gt;The NYC AI community (I could do both a less personal reflection on the state and breadth of the community, but separately I&amp;rsquo;m also interested in exploring what meeting new people means to me at this point in my life)&lt;/li&gt;
&lt;li&gt;Travel plans: Poland and Hawaii&lt;/li&gt;
&lt;li&gt;Unhurried curiosity&lt;/li&gt;
&lt;li&gt;Updates on the automation systems I use throughout my life (after work activities, automatic transaction log, bieber bot, GPT-4 newsletter, go note go, kangaroo autoresponder, etc.)&lt;/li&gt;
&lt;li&gt;The &amp;ldquo;Say Something Nice&amp;rdquo; kindness game&lt;/li&gt;
&lt;li&gt;The &amp;ldquo;Alex&amp;rsquo;s Lonely World&amp;rdquo; text adventure game&lt;/li&gt;
&lt;li&gt;An interesting one is &amp;ldquo;who are the people whose content you see and attend to online?&amp;rdquo;. It&amp;rsquo;s easy to lose sight of this and of how much control you have over this. Offline too, I suppose!&lt;/li&gt;
&lt;li&gt;Mini hack sessions, writing club, demo nights, shakshuka brunches&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;plan-for-writing-going-forward&#34;&gt;Plan for writing going forward&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;m hopeful that through this lowish effort reactivation snippet, I&amp;rsquo;ll be more likely to write additional snippets in the coming days and weeks.
However, July is a travel-packed and busy month for me, which can make keeping up with habits more difficult.
So it&amp;rsquo;s entirely possible I&amp;rsquo;ll require a second &amp;ldquo;reactivation snippet&amp;rdquo; later rather than getting solidly back into snippet writing in the short term.
That said, I do have lots of things listed above that I would enjoy writing about, so there&amp;rsquo;s a small chance this individual snippet gives me the motivation that I need.&lt;/p&gt;
&lt;p&gt;I will of course take a Go Note Go on all of my travels, so I will certainly be writing! I just may be writing privately, rather than these slightly more public pieces like I would prefer.&lt;/p&gt;
&lt;h3 id=&#34;plan-for-greetings-going-forward&#34;&gt;Plan for greetings going forward&lt;/h3&gt;
&lt;p&gt;As for asking the &amp;ldquo;what&amp;rsquo;s alive in you?&amp;rdquo; question more often, the funny looks are the main impediment for its use for me. I can mitigate this with a bit of exposition around asking the question.
For example, sharing how the question entered my own life alongside asking it can help cut through the quizzical looks a bit and keep the conversation comfortable.
So, I suppose my plan is simply to take things one conversation at a time, and use the greetings and questions that feel most appropriate as I go.
Feel free to ask these questions of me though!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Lower Bound Tech Tree (Incomplete)</title>
      <link>https://davidbieber.com/snippets/2023-03-25-tech-tree/</link>
      <pubDate>Sat, 25 Mar 2023 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2023-03-25-tech-tree/</guid>
      
      <description>&lt;h2 id=&#34;trying-to-reason-about-the-future&#34;&gt;Trying to reason about the future&lt;/h2&gt;
&lt;p&gt;With all the advances in artificial intelligence, I am trying to wrap my head around where technology is going.
(I finally feel comfortable saying I work in AI now, not just machine learning!)
I want to think clearly about what the world will look like in a month, a year, a decade.
With the rate of advancement happening today, and the wide range of possibilities for where we&amp;rsquo;re headed, coming up with good projections requires careful thinking.&lt;/p&gt;
&lt;h2 id=&#34;defining-a-lower-bound-tech-tree&#34;&gt;Defining a lower bound tech tree&lt;/h2&gt;
&lt;p&gt;To help organize my thinking, my idea is to build what I am terming a &lt;strong&gt;lower bound tech tree&lt;/strong&gt;. I&amp;rsquo;ve asked GPT-4 to build such a tree, which you can play with below.&lt;/p&gt;
&lt;p&gt;A lower bound tech tree is a tool to help you make estimates of the upper bound for how long it will take to reach some minimal (aka lower bound) level of technology (or better!).&lt;/p&gt;
&lt;p&gt;Take household robots as an example. When will we have robots that can perform a range of domestic activities, like folding laundry, washing and putting away dishes, and cleaning irregular surfaces? For any particular vision of what such a robot might look like, one can come up with an estimate for how long will be before we can realize this vision. E.g. one might imagine a bipedal robot with stereo vision and a 6 DOF arm, and estimate it will be six years before this becomes available for general consumers. However, we might be able to achieve the same purpose (automating domestic activities) sooner via a different vision. Hence, the six year estimate is an estimate of the upper bound on how long it will take to get the level of technology we&amp;rsquo;re interested in, and the capabilities listed constitute a lower bound on the quality of the technology we estimate will be available in that time.&lt;/p&gt;
&lt;p&gt;One metric that I&amp;rsquo;m interested in is: What fraction of the GitHub issues available on January 1, 2023 can be solved by an automated system? Over time, the issues people open on GitHub will increase in complexity, so to make the metric meaningful, we hold the set of issues that we&amp;rsquo;re interested in fixed, even as the capabilities of our programming tools increases.&lt;/p&gt;
&lt;p&gt;A technology we might envision is a programming tool where directly in the editor, you can type with natural language text, and it will write the code for you. Another we might envision is being able to open a GitHub issue and have an AI agent open a PR. These are things we can do at one level of quality today, and will be able to do at a much higher level of quality tomorrow. But by the time the quality reaches the point where we will have &amp;ldquo;achieved&amp;rdquo; this technology, will we still need it? I don&amp;rsquo;t have the answer to that question, but that is the line of thinking that leads me to call this a lower bound tech tree.&lt;/p&gt;
&lt;p&gt;Here, you can play with the Tech Tree that GPT-4 put together. It didn&amp;rsquo;t get too much guidance, so give it a break on its choices of technologies and timelines.&lt;/p&gt;
&lt;p&gt;The main purpose of this snippet is to post the work-in-progress tech tree visualization that follows that was largely assembled via GPT-4. You can ask it to add additional technologies to the visualization if you first paste in your OpenAI API key (it&amp;rsquo;s never sent to my server, just used locally).&lt;/p&gt;
&lt;style&gt;
  #techTreeContainer {
    width: 800px;
    height: 600px;
    border: 1px solid black;
    overflow: auto;
  }

  #techTreeCanvas {
    display: block;
  }

  .tech {
    font-family: Arial, sans-serif;
    font-size: 12px;
    fill: white;
  }

  .tech rect {
    fill: #1a8cff;
  }

  .yearLabel {
    font-family: Arial, sans-serif;
    font-size: 14px;
    fill: black;
  }

  #techInput {
    font-size: 14px;
    padding: 5px 10px;
    border: 1px solid #ccc;
    border-radius: 3px;
    width: 60%;
    margin-top: 10px;
  }

  #submitBtn {
    font-size: 14px;
    padding: 5px 10px;
    border: 1px solid #1a8cff;
    background-color: #1a8cff;
    color: white;
    border-radius: 3px;
    cursor: pointer;
    margin-top: 10px;
    margin-left: 10px;
  }

  label {
    display: inline-block;
    margin-top: 10px;
    font-size: 14px;
  }

  #apiKeyInput {
    font-size: 14px;
    padding: 5px 10px;
    border: 1px solid #ccc;
    border-radius: 3px;
    width: 50%;
    margin-top: 10px;
    margin-left: 10px;
  }
&lt;/style&gt;
&lt;div id=&#34;techTreeContainer&#34;&gt;
  &lt;canvas id=&#34;techTreeCanvas&#34; width=&#34;1000&#34; height=&#34;800&#34;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;input type=&#34;text&#34; id=&#34;techInput&#34; placeholder=&#34;Enter technology name&#34; /&gt;
  &lt;button id=&#34;submitBtn&#34;&gt;Submit&lt;/button&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;label for=&#34;apiKeyInput&#34;&gt;OpenAI API Key:&lt;/label&gt;
  &lt;input type=&#34;text&#34; id=&#34;apiKeyInput&#34; placeholder=&#34;Enter your OpenAI API Key&#34; /&gt;
&lt;/div&gt;
&lt;script&gt;
  const canvas = document.getElementById(&#39;techTreeCanvas&#39;);
  const ctx = canvas.getContext(&#39;2d&#39;);

  const techTree = [
    [
      { id: 4, title: &#39;Deep Q-Networks&#39;, desc: &#39;A combination of deep neural networks and Q-learning, used to solve complex reinforcement learning problems&#39;, x: 100, y: 50 },
      { id: 5, title: &#39;Policy Gradient Methods&#39;, desc: &#39;A class of reinforcement learning algorithms that optimize the policy directly by computing the gradient of the expected return&#39;, x: 100, y: 150 },
      { id: 6, title: &#39;Actor-Critic Methods&#39;, desc: &#39;A class of reinforcement learning algorithms that combine both value-based and policy-based methods&#39;, x: 100, y: 250 },
      { id: 7, title: &#39;Transformers&#39;, desc: &#39;A type of neural network architecture designed for sequence-to-sequence tasks, such as language translation and text summarization&#39;, x: 100, y: 350 },
      { id: 8, title: &#39;BERT&#39;, desc: &#39;Bidirectional Encoder Representations from Transformers, a pre-trained language model used for various NLP tasks&#39;, x: 100, y: 450 },
      { id: 9, title: &#39;GPT&#39;, desc: &#39;Generative Pre-trained Transformer, a large-scale language model used for natural language understanding and generation&#39;, x: 100, y: 550 },
      { id: 10, title: &#39;Convolutional Neural Networks&#39;, desc: &#39;A type of neural network architecture that is particularly effective at processing grid-like input data, such as images&#39;, x: 100, y: 650 },
      { id: 11, title: &#39;Object Detection&#39;, desc: &#39;A computer vision task that involves identifying and localizing objects within an image or a video&#39;, x: 100, y: 750 },
      { id: 12, title: &#39;Semantic Segmentation&#39;, desc: &#39;A computer vision task that involves classifying each pixel in an image according to the object or region it belongs to&#39;, x: 100, y: 850 }
    ],
    [
      { id: 1, title: &#39;Reinforcement Learning&#39;, desc: &#39;An area of machine learning that focuses on training models to make decisions by learning from interactions with an environment&#39;, x: 300, y: 100, dependencies: [{id: 4, time: &#39;6 months&#39;}, {id: 5, time: &#39;9 months&#39;}, {id: 6, time: &#39;12 months&#39;}] },
      { id: 2, title: &#39;Natural Language Processing&#39;, desc: &#39;A subfield of AI that focuses on enabling computers to understand, interpret, and generate human language&#39;, x: 300, y: 300, dependencies: [{id: 7, time: &#39;6 months&#39;}, {id: 8, time: &#39;9 months&#39;}, {id: 9, time: &#39;12 months&#39;}] },
      { id: 3, title: &#39;Computer Vision&#39;, desc: &#39;A field of AI that enables computers to interpret and understand visual information from the world&#39;, x: 300, y: 600, dependencies: [{id: 10, time: &#39;6 months&#39;}, {id: 11, time: &#39;9 months&#39;}, {id: 12, time: &#39;12 months&#39;}] }
    ],
    [
      { id: 13, title: &#39;Artificial General Intelligence&#39;, desc: &#39;A form of AI that has the ability to understand, learn, and apply knowledge across a wide range of tasks, similar to human intelligence&#39;, x: 500, y: 350, dependencies: [{id: 1, time: &#39;6 months&#39;}, {id: 2, time: &#39;9 months&#39;}, {id: 3, time: &#39;12 months&#39;}] }
    ]
  ];
  const rectWidth = 150;
  const rectHeight = 50;

  let selectedTech = null;
  let selectedEdgeTime = null;
  let offsetX = 0;
  let offsetY = 0;

  function drawRoundedRect(x, y, width, height, radius) {
    ctx.beginPath();
    ctx.moveTo(x + radius, y);
    ctx.lineTo(x + width - radius, y);
    ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
    ctx.lineTo(x + width, y + height - radius);
    ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
    ctx.lineTo(x + radius, y + height);
    ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
    ctx.lineTo(x, y + radius);
    ctx.quadraticCurveTo(x, y, x + radius, y);
    ctx.closePath();
    ctx.fill();
  }

  function drawTech(tech) {
    ctx.fillStyle = &#39;#1a8cff&#39;;
    drawRoundedRect(tech.x, tech.y, rectWidth, rectHeight, 5);

    ctx.fillStyle = &#39;white&#39;;
    ctx.font = &#39;14px Arial&#39;;
    ctx.fillText(tech.title, tech.x + 5, tech.y + 20);
  }

  function drawTooltip(x, y, text) {
    draw();
    const padding = 8;
    const tooltipWidth = ctx.measureText(text).width + 2 * padding;
    const tooltipHeight = 20 + padding;

    ctx.beginPath();
    ctx.rect(x, y, tooltipWidth, tooltipHeight);
    ctx.fillStyle = &#39;rgba(0, 0, 0, 0.8)&#39;;
    ctx.fill();
    ctx.closePath();

    ctx.font = &#39;12px Arial&#39;;
    ctx.fillStyle = &#39;white&#39;;
    ctx.fillText(text, x + padding, y + tooltipHeight - padding);
  }

  function drawDependencies(tech) {
    if (!tech.dependencies) return;

    tech.dependencies.forEach(dependencyIdTime =&gt; {
      const dependencyId = dependencyIdTime.id;
      const dependency = techTree.flat().find(t =&gt; t.id === dependencyId);
      ctx.beginPath();
      ctx.moveTo(dependency.x + rectWidth, dependency.y + rectHeight / 2);
      ctx.lineTo(tech.x, tech.y + rectHeight / 2);
      ctx.stroke();

      const timeLabelX = (tech.x + dependency.x + rectWidth) / 2;
      const timeLabelY = (tech.y + dependency.y) / 2;

      ctx.font = &#39;12px Arial&#39;;
      ctx.fillStyle = &#39;black&#39;;
      ctx.fillText(dependencyIdTime.time, timeLabelX - ctx.measureText(dependencyIdTime.time).width / 2, timeLabelY);
      ctx.setTransform(1, 0, 0, 1, 0, 0); // Reset the transformation matrix to avoid unwanted side effects

      // Attach the unique identifier as an attribute
      ctx.canvas.setAttribute(`time-${dependencyId}-${tech.id}`, `${timeLabelX},${timeLabelY}`);
    });
  }

  function drawYearLabels() {
    for (let i = 0; i &lt; techTree.length; i++) {
      const xPos = 100 + i * 200;
      ctx.font = &#39;16px Arial&#39;;
      ctx.fillStyle = &#39;black&#39;;
      const yearText = (2022 + i).toString();
      const textWidth = ctx.measureText(yearText).width;
      ctx.fillText(yearText, xPos + rectWidth / 2 - textWidth / 2, 50);
    }
  }

  function isPointInEdgeTimeLabel(x, y, depIdTime, tech) {
    const dependency = techTree.flat().find(t =&gt; t.id === depIdTime.id);
    const timeLabelX = (tech.x + dependency.x + rectWidth) / 2;
    const timeLabelY = (tech.y + dependency.y) / 2;

    ctx.font = &#39;12px Arial&#39;;
    const timeLabelWidth = ctx.measureText(depIdTime.time).width;
    const timeLabelHeight = parseInt(ctx.font, 10);

    const left = timeLabelX - timeLabelWidth / 2;
    const right = timeLabelX + timeLabelWidth / 2;
    const top = timeLabelY - timeLabelHeight / 2;
    const bottom = timeLabelY + timeLabelHeight / 2;

    return x &gt;= left &amp;&amp; x &lt;= right &amp;&amp; y &gt;= top &amp;&amp; y &lt;= bottom;
  }

  function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drawYearLabels();

    techTree.forEach(column =&gt; {
      column.forEach(tech =&gt; {
        drawDependencies(tech);
        drawTech(tech);
      });
    });
  }

  function isPointInRect(x, y, tech) {
    return x &gt; tech.x &amp;&amp; x &lt; tech.x + rectWidth &amp;&amp; y &gt; tech.y &amp;&amp; y &lt; tech.y + rectHeight;
  }

  let initialMouseX = 0;
  let initialEdgeTime = 0;
  canvas.addEventListener(&#39;mousedown&#39;, e =&gt; {
    const rect = canvas.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;

    for (const tech of techTree.flat()) {
      if (isPointInRect(x, y, tech)) {
        selectedTech = tech;
        offsetX = x - tech.x;
        offsetY = y - tech.y;
        tech.initialX = tech.x;
        tech.initialY = tech.y;
        break;
      }
    }

    if (!selectedTech) {
      for (const tech of techTree.flat()) {
        if (tech.dependencies) {
          for (const depIdTime of tech.dependencies) {
            if (isPointInEdgeTimeLabel(x, y, depIdTime, tech)) {
              selectedEdgeTime = { tech, depIdTime };
              initialMouseX = e.clientX - rect.left;
              initialEdgeTime = parseInt(selectedEdgeTime.depIdTime.time.match(/\d+/)[0], 10);
              break;
            }
          }
        }
      }
    }
  });

  canvas.addEventListener(&#39;mousemove&#39;, e =&gt; {
    const rect = canvas.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;

    if (selectedTech) {
      const newX = x - offsetX;
      const newY = y - offsetY;

      selectedTech.x = Math.min(Math.max(newX, selectedTech.initialX - 150), selectedTech.initialX + 150);
      selectedTech.y = Math.min(Math.max(newY, selectedTech.initialY - 150), selectedTech.initialY + 150);

      draw();
    }

    if (selectedEdgeTime) {
      const timeChange = Math.round((x - initialMouseX) / 10);

      // Update the time amount based on the initial time value and the time change
      const newTime = Math.max(initialEdgeTime + timeChange, 1);
      selectedEdgeTime.depIdTime.time = newTime + &#34; months&#34;;
      draw();
    }

    let hoveredTech = null;
    for (const tech of techTree.flat()) {
      if (isPointInRect(x, y, tech)) {
        hoveredTech = tech;
        break;
      }
    }

    if (hoveredTech) {
      drawTooltip(x, y, hoveredTech.desc);
    }
  });

  canvas.addEventListener(&#39;mouseup&#39;, releaseTech);
  canvas.addEventListener(&#39;mouseleave&#39;, releaseTech);

  function releaseTech() {
    selectedEdgeTime = null;

    if (!selectedTech) return;

    selectedTech.x = selectedTech.initialX;
    selectedTech.y = selectedTech.initialY;

    selectedTech = null;
    draw();
  }

  async function chatCompletion(text) {
    const messages = [
        {
            role: &#39;system&#39;,
            content: &#39;You are a helpful assistant.&#39;,
        },
        {
            role: &#39;user&#39;,
            content: text,
        }
    ];
    const apiKey = apiKeyInput.value;
    const response = await fetch(&#39;https://api.openai.com/v1/chat/completions&#39;, {
        method: &#39;POST&#39;,
        headers: {
            &#39;Content-Type&#39;: &#39;application/json&#39;,
            &#39;Authorization&#39;: `Bearer ${apiKey}`,
        },
        body: JSON.stringify({
            &#34;model&#34;: &#34;gpt-4&#34;,
            &#34;messages&#34;: messages,
            &#34;temperature&#34;: 0
        })
    });
    const responseData = await response.json();
    return responseData.choices[0].message.content.trim();
  }

  async function addTechToTechTree(tech) {
    // Get description of the technology
    const descriptionPrompt = `Give a one-line description of the technology: ${tech}`;
    const description = await chatCompletion(descriptionPrompt);
    console.log(description);

    // List the existing technologies on the tech tree
    const existingTechs = techTree.flat();
    const existingTechsList = existingTechs.map((t, index) =&gt; `${index + 1}. ${t.title}`).join(&#39;\n&#39;);

    // Get dependencies/enabling technologies of the technology
    const dependenciesPrompt = `We are building a tech tree. The following technologies are already on our tech tree:
${existingTechsList}

List the dependencies or enabling technologies of ${tech}.
Include any of the technologies from the tech tree that are enabling technologies of ${tech}, as well as any such technologies not already on the tech tree.

List just one technology per line, and just the name of the technology (no descriptions, no line numbers, no bullet points, no blank lines).
`;
    const dependenciesText = await chatCompletion(dependenciesPrompt);
    console.log(dependenciesText);
    const allDependencies = dependenciesText.split(&#39;\n&#39;).map(dep =&gt; dep.trim());

    // Filter dependencies based on existing technologies
    const filteredDependencies = allDependencies.filter(dep =&gt; existingTechs.some(existingTech =&gt; existingTech.title === dep));

    // Add the technology and its information to the techTree data
    const newTech = {
      id: techTree.flat().length + 1,
      title: tech,
      desc: description,
      x: 100 + (techTree.length - 1) * 200,
      y: 100 + (techTree[techTree.length - 1].length) * 100,
      dependencies: filteredDependencies.map(dep =&gt; ({ id: existingTechs.find(existingTech =&gt; existingTech.title === dep).id, time: &#39;6 months&#39; })),
    };
    techTree[techTree.length - 1].push(newTech);

    // Redraw the tech tree
    draw();
  }

  const techInput = document.getElementById(&#39;techInput&#39;);
  const submitBtn = document.getElementById(&#39;submitBtn&#39;);

  techInput.addEventListener(&#39;keyup&#39;, (e) =&gt; {
    if (e.key === &#39;Enter&#39;) {
      addTechToTechTree(techInput.value);
      techInput.value = &#39;&#39;;
    }
  });

  submitBtn.addEventListener(&#39;click&#39;, () =&gt; {
    addTechToTechTree(techInput.value);
    techInput.value = &#39;&#39;;
  });

  const apiKeyInput = document.getElementById(&#39;apiKeyInput&#39;);

  function saveAPIKey() {
    localStorage.setItem(&#39;openai_api_key&#39;, apiKeyInput.value);
  }

  function loadAPIKey() {
    const storedAPIKey = localStorage.getItem(&#39;openai_api_key&#39;);
    if (storedAPIKey) {
      apiKeyInput.value = storedAPIKey;
    }
  }

  apiKeyInput.addEventListener(&#39;input&#39;, saveAPIKey);

  // Load the API key from local storage when the page loads
  loadAPIKey();
  draw();
&lt;/script&gt;
</description>
    </item>
    
    <item>
      <title>Personal Newsletter (Just for me)</title>
      <link>https://davidbieber.com/snippets/2023-03-18-personal-newsletter/</link>
      <pubDate>Sat, 18 Mar 2023 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2023-03-18-personal-newsletter/</guid>
      
      <description>&lt;p&gt;I write a lot. Every night. Every day. I&amp;rsquo;m constantly writing. And, unlike many of the people I know who similarly take lots of notes, I also regularly read what I write. However, the nature of how I write leaves my writing messy (full of typos) and disjointed (writing on one topic might be scattered across dozens of pages, with lots of unrelated thoughts interspersed between).&lt;/p&gt;
&lt;p&gt;About a year ago, I had the idea to hire an editor / writer to help me use all this writing a bit more effectively. My idea at the time was that once a month, I would bundle up everything I&amp;rsquo;d written that month, and send it to my editor. They would read through it, clean up all the typos, and also assemble a monthly newsletter of sorts, just for me. The newsletter would have a section for each major topic in my notes &amp;ndash; each idea that I revisited more than once &amp;ndash; and it would provide a quick recap of my thinking on that topic.&lt;/p&gt;
&lt;p&gt;I never hired that editor. Instead, GPT-4 was released, and I implemented this newsletter idea for myself instead.&lt;/p&gt;
&lt;h2 id=&#34;the-newsletter&#34;&gt;The Newsletter&lt;/h2&gt;
&lt;p&gt;I now receive, courtesy of Bieber Bot and my messager server, a personalized newsletter twice a week. The newsletter contains a bunch of sections: upcoming plans, things I&amp;rsquo;ve been thinking about, the dominant emotions from the week, etc. Each section is presented in a nice little round-cornered box, with concise text showcasing the highlights from my notes.&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t a newsletter that I would ever send out to an audience &amp;ndash; it&amp;rsquo;s highly personal! But receiving it in my inbox is a joy. It reminds me of the people I want to reach out to. It reminds me of all the clever little ideas I had throughout the week, that I might not have thought about again for a while. It reminds me of things I&amp;rsquo;d been meaning to buy or do.&lt;/p&gt;
&lt;p&gt;Receiving this newsletter helps me connect better with myself by resurfacing all these old ideas I&amp;rsquo;d had throughout the week.&lt;/p&gt;
&lt;h2 id=&#34;newsletter-features&#34;&gt;Newsletter Features&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Questions.&lt;/strong&gt; In my first pass at creating the newsletter, I&amp;rsquo;ve given GPT-4 a list of questions to answer using the last 5 days of my notes. The newsletter contains one section per question. Here&amp;rsquo;s the list of questions I started out with, which I expect to refine over time.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What are all my open TODOs?&lt;/li&gt;
&lt;li&gt;What are all the things I want to buy?&lt;/li&gt;
&lt;li&gt;What are all my upcoming plans?&lt;/li&gt;
&lt;li&gt;What are some ideas I seem to keep revisiting?&lt;/li&gt;
&lt;li&gt;What are my accomplishments from the past week?&lt;/li&gt;
&lt;li&gt;List all the people I wanted to reach out to and what I wanted to say to them.&lt;/li&gt;
&lt;li&gt;What are the most interesting ideas from my notes?&lt;/li&gt;
&lt;li&gt;What are the big recurring themes in my notes?&lt;/li&gt;
&lt;li&gt;Are there any things in my notes that didn&amp;rsquo;t make sense to you?&lt;/li&gt;
&lt;li&gt;What are the dominant emotions found in the notes?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Digestability.&lt;/strong&gt; For each question, GPT-4 prepares concise content that&amp;rsquo;s easy to digest. It arranges the sections in a 2-column layout.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Citing sources.&lt;/strong&gt; I&amp;rsquo;ve also asked GPT-4 to include links back to the original notes that it is using to answer the questions. To do this, I include in GPT&amp;rsquo;s view of my notes a unique ID for each note (essentially one ID per block of text). I then have GPT use these ids to cite which notes its using in every sentence that it writes. To me, it&amp;rsquo;s remarkable that this works.&lt;/p&gt;
&lt;h2 id=&#34;why-are-you-writing-all-this-to-begin-with&#34;&gt;Why are you writing all this to begin with?&lt;/h2&gt;
&lt;p&gt;One of the personal projects I&amp;rsquo;ve gotten the most value out of is called 
&lt;a href=&#34;https://davidbieber.com/projects/go-note-go/&#34;&gt;Go Note Go&lt;/a&gt;. It&amp;rsquo;s a headless keyboard (a computer keyboard with no screen) that I can write on or speak to, and anything I write on it (or say to it, after pushing the record button), gets transcribed into my notes (for me, this is Roam Research, but Go Note Go supports 7-8 different note-taking systems, so if you want to use it, I&amp;rsquo;m sure wherever you like to keep your writing is fine.)&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve found Go Note Go incredibly rewarding. Whether I&amp;rsquo;m driving somewhere, drifting off to sleep, sitting at my desk, or taking a shower, it&amp;rsquo;s there to help me capture any thoughts I want to remember. Unlike a voice memo or Apple Notes, using it isn&amp;rsquo;t disruptive (to myself or others). Even when just sitting at a desk, I get a great sense of relief turning away from my computer monitor toward Go Note Go to write; it&amp;rsquo;s freeing, and helps me think clearly. I could go on about Go Note Go indefinitely, and if you want to learn more or to build your own, 
&lt;a href=&#34;https://davidbieber.com/tags/go-note-go/&#34;&gt;you can do so here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A second personal project that I also use to take notes on the go is my personal Voice Assistant. I have a phone number I can call to either leave myself notes or to talk with GPT. These notes / conversations also end up in my notes in Roam, and hence can end up in my newsletter. I prefer this over a standard voice note-taking app because it works well with car play, so I can use it while I&amp;rsquo;m driving.&lt;/p&gt;
&lt;h2 id=&#34;building-the-newsletter&#34;&gt;Building the Newsletter&lt;/h2&gt;
&lt;p&gt;Actually building the newsletter was delightful. Using GPT-4 to process my notes was simple using OpenAI&amp;rsquo;s Python API. Despite this simplicity, I found it faster to have GPT-4 itself write the code that constructs the newsletter than to write it myself.&lt;/p&gt;
&lt;p&gt;I also wanted the newsletter to be stylized nicely, not just a wall of text. I haven&amp;rsquo;t done much front-end development work in recent years, but GPT-4 was happy to write the HTML and CSS to make the email exactly as desired (2 columns of rounded corner sections, each with header and content). The email-sending library I was using (a part of my Messager platform) didn&amp;rsquo;t support sending HTML emails though, but GPT-4 had no trouble updating the library to support this.&lt;/p&gt;
&lt;p&gt;Overall GPT-4 made building both the automatically-writing-the-newsletter and assisting-me-writing-the-software-that-creates-and-sends-the-newsletter pieces simple and quite fun.
It reminds me of the childhood joy of learning to program; computers are magic, once again.&lt;/p&gt;
&lt;h2 id=&#34;newsletter-upkeep&#34;&gt;Newsletter Upkeep&lt;/h2&gt;
&lt;p&gt;I expect that over the next few weeks, as the first installments of the newsletter start showing up in my email, I&amp;rsquo;ll have lots of tweaks and improvements I&amp;rsquo;ll want to make. For one, I look forward to iterating on the list of questions and sections in the newsletter. I&amp;rsquo;m also likely to add some filtering to my notes before they get sent to GPT, to ensure that personal or confidential pieces aren&amp;rsquo;t sent to OpenAI. I&amp;rsquo;m also likely to refine the &amp;ldquo;preamble&amp;rdquo; and prompts GPT sees, so it has more context about topics I write about frequently, and to better align GPT&amp;rsquo;s output with my morning interests and needs.&lt;/p&gt;
&lt;p&gt;As an example, I&amp;rsquo;m excited to try having GPT use HTML&amp;rsquo;s summary/details feature to create a cleaner newsletter layout while allowing deep dives by expanding the summaries. Additionally, I&amp;rsquo;m enthusiastic about adding deep linking back into Roam, so that I can quickly access my raw notes from anything in the newsletter.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d also love to create an experience where simply by clicking on a piece of text in the newsletter, I can start to take the appropriate action on that item. For instance, clicking on a reminder to reach out to someone could open a Gmail draft or Facebook Messenger message draft started by GPT. And If I click on a reminder to buy a backpack, it could open Amazon search results.&lt;/p&gt;
&lt;p&gt;For some items in my notes, it might even make sense for GPT to propose or take actions independently. I&amp;rsquo;m keen on exploring this idea and transforming the newsletter into more of a personal assistant experience for myself.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m confident that I&amp;rsquo;ll have a dozen more ideas and feature requests for myself and for GPT in these coming weeks, and I&amp;rsquo;m delighted to use Go Note Go to keep track of all of them &amp;ndash; only to have them show up in my personal newsletter later in the week. I fully anticipate working with GPT to implement these feature requests to continue improving my newsletter experience.&lt;/p&gt;
&lt;h2 id=&#34;conclusions-courtesy-of-gpt-4&#34;&gt;Conclusions, courtesy of GPT-4&lt;/h2&gt;
&lt;p&gt;In conclusion, using GPT-4 to create a personal newsletter has proven to be an effective and enjoyable solution for organizing and revisiting the wealth of ideas and thoughts from daily note-taking. The AI&amp;rsquo;s capabilities in processing and compiling content, as well as its assistance in coding and designing the newsletter, have demonstrated its incredible potential as a developer tool. The resulting personalized newsletter not only helps me in connecting better with myself but also serves as a powerful reminder of my ideas, emotions, and plans that would have otherwise been lost in the chaos of daily life. As GPT-4 continues to evolve, there are endless possibilities for future improvements and applications, making it an invaluable resource for both developers and individuals alike.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Writing a Tampermonkey Script with GPT-4</title>
      <link>https://davidbieber.com/snippets/2023-03-15-tampermonkey-gpt-4/</link>
      <pubDate>Wed, 15 Mar 2023 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2023-03-15-tampermonkey-gpt-4/</guid>
      
      <description>&lt;p&gt;Today I used 
&lt;a href=&#34;https://openai.com/research/gpt-4&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;GPT-4&lt;/a&gt; to implement my first ever 
&lt;a href=&#34;https://www.tampermonkey.net/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Tampermonkey&lt;/a&gt; script. It took well under half an hour, which is likely many times faster than it would have taken me alone. I am blown away by GPT-4&amp;rsquo;s programming capabilities.&lt;/p&gt;
&lt;p&gt;It started with 
&lt;a href=&#34;https://github.com/hypothesis/h/issues/7868&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;a simple feature request&lt;/a&gt; for 
&lt;a href=&#34;https://hypothes.is/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;the Hypothesis browser extension&lt;/a&gt;. For context, Hypothesis is a tool for taking notes on the web, including on PDFs.
I use it to take notes on machine learning pdfs on Arxiv. It&amp;rsquo;s a great tool, but it has a limitation: when browsing my notes, it only shows the ID of the pdf, not the name of the PDF. This makes it hard to find what I&amp;rsquo;m looking for.
So, I made a feature request on GitHub, asking if the developers of hypothesis could make the titles of pages editable. This would allow me to replace the useless IDs with the more useful titles on pdfs whenever I take notes on them.&lt;/p&gt;
&lt;p&gt;Someone suggested I could write a Greasemonkey script to do this. Their exact suggestion was:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;You can write a Greasemonkey script which parses the Arxiv PDF links on Hypothesis pages, gathers their ArxivID, queries the Arxiv ATOM API with one HTTP call (using an aggregated list of ArxivIDs as a search parameter) and updates Arxiv PDF links titles on Hypothesis pages.

Example of an API query with multiple ArxivIDs: https://export.arxiv.org/api/query?id_list=2007.12026,1706.03741,1603.00022
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At first I thought this wasn&amp;rsquo;t such a helpful suggestion. Writing a Greasemonkey script is time consuming and it wouldn&amp;rsquo;t be worthwhile for such a small usability improvement. Then I remembered GPT-4. So, I decided to proceed.&lt;/p&gt;
&lt;p&gt;Greasemonkey is for Firefox. Tampermonkey is the equivalent for Chrome. I use Chrome, so I would need a Tampermonkey script.&lt;/p&gt;
&lt;p&gt;I used GPT-4 to write the script. This is not a trivial script by any stretch of the imagination. It involves parsing the DOM on the Hypothesis page to find references to Arxiv, querying the Arxiv API (but only after dividing the IDs into batches), parsing the XML results returned by the API, and again parsing and updating the DOM on the Hypothesis page to update the results. In order to do all this, the developer needs to understand what the DOM looks like on the Hypothesis page, and what the format of the Arxiv API results XML looks like, in order to get the parsing correct. It took a few back-and-forths, but GPT-4 did a remarkable job of writing the script.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what our interaction looked like:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;1. Me (Initial prompt): `Write a tampermonkey script that parses the Arxiv PDF links on Hypothesis pages, gathers their ArxivID, queries the Arxiv ATOM API with one HTTP call (using an aggregated list of ArxivIDs as a search parameter) and updates Arxiv PDF links titles on Hypothesis pages.`

GPT-4: &amp;lt;Attempt 1 at script&amp;gt;

2. Me: `The HTML for one of the rows on the hypothesis page is:
...
In this example the text to update is &amp;quot;1904.09751.pdf&amp;quot; which should be replaced with the title`

GPT-4: &amp;lt;Attempt 2 at script&amp;gt;

3. Me: How do I view the script&#39;s logs if it isn&#39;t working?

GPT-4: Explains how to get the logs

4. Me: _&amp;lt;pastes error message&amp;gt;_

GPT-4: _&amp;lt;Fixes error message&amp;gt;_

5. Me: Here is the format returned by the arxiv.org api call we&#39;re making: _&amp;lt;pastes example Arxiv API output&amp;gt;_

Notice the arxiv id can end with e.g. v1 -- we can safely strip that part.
Let&#39;s also add debug logging, e.g. logging the arxivIDs found on the hypothesis page and any other useful debug info

GPT-4: _&amp;lt;Fixes the v1 stripping and adds logging&amp;gt;_

6. Me: The arxiv API only returns the results for the first 10 ids passed to it.

GPT-4: _&amp;lt;Adds batching of API calls&amp;gt;_

7. Me: _&amp;lt;Describes an edge case&amp;gt;_: The title can also be something like 1607.06450v1.pdf -- in that case we should get the id as 1607.06450, dropping the &amp;quot;v1&amp;quot; part

GPT-4: _&amp;lt;Handles the edge case&amp;gt;_
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
&lt;a href=&#34;https://gist.github.com/dbieber/c3198a1ceeb86fa823df305a76907afa&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Here&amp;rsquo;s the final script it came up with.&lt;/a&gt;. It&amp;rsquo;s 112 lines of reasonably well organized Javascript. And it gets the job done. Now, when I visit my Hypothesis notes, the title of every paper is shown clearly, not just its inscrutable Arxiv ID.&lt;/p&gt;
&lt;p&gt;As you can see from the abbreviated transcript above, there were only seven back-and-forths between me and the model. In that time, the model behaved sensibly all throughout. It never once made a silly slip-up, which was common behavior for previous models.&lt;/p&gt;
&lt;p&gt;In those seven back-and-forths, I used one (1) to share the overall task, four (2, 5, 6, and 7) to share information about the data being manipulated, one (3) to ask for help, and one (4) to paste an error message for GPT to debug.
If I&amp;rsquo;d had more foresight, I expect I could have included the data from (2, 5, 6, and 7) all in my initial query.&lt;/p&gt;
&lt;p&gt;During development, I would manually copy GPT-4&amp;rsquo;s code into Tampermonkey, save it, and refresh Hypothesis to see the changes. If I got an error, or if the behavior wasn&amp;rsquo;t exactly what I wanted, I simply told GPT and waited for it to update the code. GPT-4&amp;rsquo;s output generation is slow compared to other AI models, and there was some waiting time as it wrote its responses. I really felt like I had delegated work to an AI worker, and could easily see myself managing a fleet of such workers, all working toward different goals concurrently. I can also see a future where one AI worker is itself responsible for delegating work to a fleet of such workers; it doesn&amp;rsquo;t need to be a human doing all that delegation.&lt;/p&gt;
&lt;p&gt;Overall, GPT-4 behaved as a professional and speedy developer throughout the entire duration of the task. I would be delighted to work with them again on future projects.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Everyday Robots</title>
      <link>https://davidbieber.com/snippets/2023-02-24-everyday-robots/</link>
      <pubDate>Fri, 24 Feb 2023 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2023-02-24-everyday-robots/</guid>
      
      <description>&lt;p&gt;Whoa! Hello there! Can&amp;rsquo;t wait to learn what you can do!&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;I say &amp;ldquo;Can you check the time for me?&amp;rdquo; and you walk over to a clock and look at it.&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Can you see how much shampoo is left?&lt;br/&gt;
Send me a picture of what&amp;rsquo;s in the fridge.&lt;br/&gt;
Take out the trash.&lt;br/&gt;
Check if the milk is spoiled and put it in the trash.&lt;br/&gt;
Very gently move the jigsaw puzzle into the other room.&lt;br/&gt;
Quick! Unplug the toaster!&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Put out the fire.&lt;br/&gt;
Can you plug my phone in, please?&lt;br/&gt;
Open the window?&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s rearrange the furniture &amp;ndash; where do you think the couch should go?&lt;br/&gt;
Can you check what page I was on in my book? I think it&amp;rsquo;s on the couch.&lt;br/&gt;
Can you help me find my keys?&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Help me install this sconce.&lt;br/&gt;
Make the bed.&lt;br/&gt;
Do the dishes.&lt;br/&gt;
Clean the counter.&lt;br/&gt;
Vaccuum the carpet.&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Can you open the blinds for me in the morning?&lt;br/&gt;
Please have breakfast ready at 8am.&lt;br/&gt;
Do you remember if I brushed my teeth yet?&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s work out together.&lt;br/&gt;
Let&amp;rsquo;s dance.&lt;br/&gt;
Now, let&amp;rsquo;s play a board game.&lt;br/&gt;
Can you write a letter?&lt;br/&gt;
Can you write a letter in my handwriting??&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Put on this motion capture device, we&amp;rsquo;re going to calibrate you.&lt;br/&gt;
Bring me my own motion capture device &amp;ndash; I want to collect some practice demonstrations for you.&lt;br/&gt;
I seem to have left my motion capture device in New Haven, so watch carefully &amp;ndash; I&amp;rsquo;m going to show you how I clean the mirror.&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;First I pick up this bottle, and I make sure the spray nozzle is set to the on position. It says &amp;ldquo;On&amp;rdquo; here.&lt;br/&gt;
Then I point the bottle at the mirror and spray like this, pulling the trigger to spray.&lt;br/&gt;
I wipe the wet off the mirror to remove any dirt that built up.&lt;br/&gt;
Now you try.&lt;br/&gt;
Oh, the way I know if I succeeded is the mirror looks clean!&lt;br/&gt;
Give it a few tries. You&amp;rsquo;ll figure it out.&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Oh wow, you got it on your first try &amp;ndash; I guess this isn&amp;rsquo;t a new skill for you?&lt;br/&gt;
Oh, someone taught you on a different mirror somewhere else around the world, so you already knew how to do this.&lt;br/&gt;
But you still had to figure out how to do it in this new environment, and you did great!&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Can you clean up the mess you made when you dropped that plate earlier?&lt;br/&gt;
Ouch! You rolled over the dog&amp;rsquo;s tail!&lt;br/&gt;
Negative reward! &amp;ldquo;No&amp;rdquo;, &amp;ldquo;No&amp;hellip;&amp;rdquo;, &amp;ldquo;Bad robot&amp;hellip;&amp;quot;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Very good!&amp;quot;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Oh wow, thank you for this unprompted gift &amp;ndash; yes, you get reward for that, that was wonderful, that was very kind.&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Thank you for the elbow pat, little robot.&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t forget to oil your joints!&lt;br/&gt;
Let&amp;rsquo;s order some new oil for you.&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Hmm, encoding your reward to just my voice doesn&amp;rsquo;t seem sufficient with the hacks going around &amp;ndash; we&amp;rsquo;ll need a password or 2fa chip as well.&lt;br/&gt;
What a shame.&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Does it make you sad that I&amp;rsquo;m thinking about buying a newer model?&lt;br/&gt;
I&amp;rsquo;m gonna miss you everyday, Robbie.&lt;br/&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>On why writing is hard</title>
      <link>https://davidbieber.com/snippets/2023-01-22-writing-is-hard/</link>
      <pubDate>Sun, 22 Jan 2023 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2023-01-22-writing-is-hard/</guid>
      
      <description>&lt;p&gt;Writing can be challenging. It can feel slow at times. For me, my 
&lt;a href=&#34;https://davidbieber.com/snippets/2019-12-30-writing-for-no-audience/&#34;&gt;snippets systems&lt;/a&gt; goes a long way toward mitigating this. In this particular snippet, I present a taxonomy of why writing is hard.&lt;/p&gt;
&lt;h3 id=&#34;difficulty-1-rereading&#34;&gt;Difficulty 1: Rereading&lt;/h3&gt;
&lt;details&gt;&lt;summary&gt;Rereading slows me down.&lt;/summary&gt;
&lt;p&gt;It can consume significant time, for little benefit compared with writing unwritten sections of the piece.&lt;/p&gt;
&lt;p&gt;I include here going back and making changes or insertions earlier in the writing.&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t meant to diminish the value of revisions or editing. There is a time and place for those. That time and place generally isn&amp;rsquo;t while you&amp;rsquo;re writing your piece though.&lt;/p&gt;
&lt;/details&gt;
&lt;h3 id=&#34;difficulty-2-minor-in-comparison-to-1-local-wordsmithing-typo-cleanup-etc&#34;&gt;Difficulty 2 (minor in comparison to #1): Local wordsmithing, typo cleanup, etc&lt;/h3&gt;
&lt;details&gt;&lt;summary&gt;As I write, I make mistakes. Fixing them as I make them slows me down.&lt;/summary&gt;
&lt;p&gt;From my experience with 
&lt;a href=&#34;https://davidbieber.com/projects/go-note-go/&#34;&gt;Go Note Go&lt;/a&gt;, I know the volume of these mistakes when uncorrected is enormous. Some of the mistakes themselves are hilariously large, like typing 
&lt;a href=&#34;https://davidbieber.com/snippets/2023-01-21-repetition/&#34;&gt;&amp;ldquo;nubdsgare&amp;rdquo; instead of &amp;ldquo;mindshare&amp;rdquo;&lt;/a&gt; because my hands weren&amp;rsquo;t lined up properly on the keyboard.&lt;/p&gt;
&lt;p&gt;Fixing this kind of mistake while you&amp;rsquo;re writing is extremely common. I recommend against it though! This of course is extremely difficult (and possibly bad) advice to follow if you&amp;rsquo;re writing with a monitor, because all those typos will distract you. They&amp;rsquo;ll tug hard at you to fix them.&lt;/p&gt;
&lt;p&gt;If, however, you are writing without a monitor, e.g. on Go Note Go, then it is much easier to ignore fixing these local mistakes until later. This can accelerate your first-draft writing significantly.&lt;/p&gt;
&lt;/details&gt;
&lt;h3 id=&#34;difficulty-3-task-switching&#34;&gt;Difficulty 3: Task switching&lt;/h3&gt;
&lt;details&gt;&lt;summary&gt;That is, &lt;b&gt;getting distracted&lt;/b&gt;. Of course getting distracted slows me down.&lt;/summary&gt;
&lt;p&gt;This could be by either internal or 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-10-01-infinite-distractions-and-getting-a-good-sear/&#34;&gt;external distractions&lt;/a&gt;. Both can be harmful toward effective writing.&lt;/p&gt;
&lt;p&gt;Understanding 
&lt;a href=&#34;https://davidbieber.com/tags/attention/&#34;&gt;the nature of distractions&lt;/a&gt; can be helpful.
Often it can be that a decision point is reached and it&amp;rsquo;s hard to decide (Difficulty #4).
It could be that making progress requires putting yourself out there, e.g. writing something that someone else will read and possibly judge, or clicking send (Difficulty #8).&lt;/p&gt;
&lt;p&gt;Maybe it&amp;rsquo;s as simple as not knowing how to spell someone&amp;rsquo;s name. &amp;ldquo;Does Marisa have one S or two? I&amp;rsquo;ll come back to writing this text later.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Maybe it&amp;rsquo;s needing to choose a name for an event. Or choosing who to invite.&lt;/p&gt;
&lt;p&gt;Maybe it&amp;rsquo;s the more common cause of distractions: something shiny and more appealing than writing catches your eye.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Let&#39;s list the mitigations for this difficulty.&lt;/summary&gt;
&lt;p&gt;&lt;strong&gt;Mitigation 1:&lt;/strong&gt; Have a clear goal, which when achieved, allows for task switching.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mitigation 2:&lt;/strong&gt; Use Go Note Go (thereby 
&lt;a href=&#34;https://davidbieber.com/snippets/2023-01-16-go-note-go-features/&#34;&gt;removing the possibility of editing, rereading, or task switching&lt;/a&gt;). This helps with Difficulties #1, #2, and #3 so far!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mitigation idea 3:&lt;/strong&gt; As a (more challenging) alternative to Go Note Go, 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-01-13-writing-tool-idea/&#34;&gt;implement rules for yourself&lt;/a&gt; that disallow editing, rereading, and task switching.&lt;/p&gt;
&lt;/details&gt;&lt;br/&gt;
&lt;p&gt;For me, these first three difficulties capture much of why writing emails, for example, can be challenging.&lt;/p&gt;
&lt;h3 id=&#34;difficulty-4-reaching-a-decision-that-you-dont-want-to-make&#34;&gt;Difficulty 4: Reaching a decision that you don&amp;rsquo;t want to make&lt;/h3&gt;
&lt;details&gt;&lt;summary&gt;Decision-making can fatigue or even end a writing session.&lt;/summary&gt;
&lt;p&gt;This is worth separating this from Difficulty 3 (Task switching) because it precedes task switching, and can generate difficulty even if it doesn&amp;rsquo;t spur task switching.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also worth breaking down further, since not all decision making difficulty is the same.&lt;/p&gt;
&lt;/details&gt;
&lt;h4 id=&#34;four-types-of-decision-making-difficulty&#34;&gt;Four types of decision making difficulty:&lt;/h4&gt;
&lt;details&gt;&lt;summary&gt;1. Decision appears to reveal inner preference&lt;/summary&gt;
&lt;p&gt;Resistance to making a decision can form if the decision would reveal (or appear to reveal) an inner preference that you don&amp;rsquo;t want to reveal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Choosing a name or a gender for a character when you want to tell the story first, and then choose their name or gender or race (or whatever characteristics are going to get implied by the name selection) later&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mitigation:&lt;/strong&gt; Just pick a name! You can always change it later.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mitigation:&lt;/strong&gt; Use a placeholder. This isn&amp;rsquo;t as good as just picking a name.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mitigation:&lt;/strong&gt; Add a note-to-self that you&amp;rsquo;ll strip on publication if that makes you feel more comfortable.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;2. Decision requires communication / external stakeholders&lt;/summary&gt;
&lt;p&gt;Decisions often require additional information not yet available, possibly requiring additional communication or back-and-forths with other people in order to obtain. This can become a blocker toward writing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Picking a place to meet, or a date and time&lt;/p&gt;
&lt;p&gt;Why is this challenging? It&amp;rsquo;s because it relies on having information that might not be available. Gathering the information might require a challenging coordination problem, possibly with chicken-and-the-egg difficulties.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mitigation:&lt;/strong&gt; Be verbose, and provide both a default suggestion as well as information about the level of flexibility in the suggestion.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mitigation:&lt;/strong&gt; Reach out to the people who can provide the information you need immediately, but be clear that you won&amp;rsquo;t necessarily wait for their response to proceed with the original task.&lt;/p&gt;
&lt;p&gt;You can then include in the original writing that you&amp;rsquo;ve reached out to gather the missing information and will follow-up soon.
In general, 
&lt;a href=&#34;https://davidbieber.com/post/2022-01-08-new-messager-setup/&#34;&gt;sending messages earlier&lt;/a&gt; indicating that you&amp;rsquo;ve received and are processing someone else&amp;rsquo;s message is a good idea. You can always write more later.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;General strategy:&lt;/strong&gt; Respond to emails immediately acknowledging receipt even if you haven&amp;rsquo;t taken the time to thoughtfully respond yet.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;3. Options are hard to choose between, because they are roughly equal in expected value&lt;/summary&gt;
&lt;p&gt;Sometimes 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-02-08-future-gameshow-host/&#34;&gt;a choice&lt;/a&gt; is just hard. Sometimes the hardest choices are hard because the expected outcomes are important, but not clearly better one way or the other.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Choosing between job offers, or between pieces of art to buy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mitigation:&lt;/strong&gt; Use the penguin approach. Then pick one as the default, and proceed to ask if each subsequent possible choice is better; if it is, update the default (aka &amp;ldquo;the penguin&amp;rdquo;) to that choice. When it comes time to finally choose, select the penguin.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;4. A decision could be difficult for another reason: because the negative consequences of the best choice are hard to stomach&lt;/summary&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; A break up or a layoff, or other form of giving someone bad news.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mitigation:&lt;/strong&gt; Be empathetic. There&amp;rsquo;s no good way to deliver bad news, but there are worse ways. Be human, and supportive.&lt;/p&gt;
&lt;/details&gt;
&lt;h3 id=&#34;difficulty-5-deciding-what-to-say&#34;&gt;Difficulty 5: Deciding what to say&lt;/h3&gt;
&lt;details&gt;&lt;summary&gt;This can appear to be a difficulty when in actuality the difficulty is in Difficulty 1: Rereading.&lt;/summary&gt;
&lt;p&gt;For example, you might finish an idea and have to decide what to write next, so you reread what you&amp;rsquo;ve written to refresh your idea. This is already slowing you down.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mitigation:&lt;/strong&gt; Make an outline.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mitigation:&lt;/strong&gt; Instead of choosing what to write (if there are two options even with your outline) as if its a final choice, realize that you can write both options and keep whichever or both that you like later, during editing.&lt;/p&gt;
&lt;p&gt;Deciding what to say can, of course, also be a difficulty in and of itself, too.&lt;/p&gt;
&lt;/details&gt;&lt;br/&gt;
&lt;p&gt;For completeness, I list three additional difficulties here without additional comment:&lt;/p&gt;
&lt;h3 id=&#34;difficulty-6-editing&#34;&gt;Difficulty 6: Editing&lt;/h3&gt;
&lt;h3 id=&#34;difficulty-7-finding-draft-readers&#34;&gt;Difficulty 7: Finding draft readers&lt;/h3&gt;
&lt;h3 id=&#34;difficulty-8-clicking-submit&#34;&gt;Difficulty 8: Clicking submit&lt;/h3&gt;
&lt;p&gt;Want to practice writing and clicking submit? 
&lt;a href=&#34;mailto:david810&amp;#43;writing-is-hard@gmail.com&#34;&gt;Say hi! Send me an email.&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Things you can do on the computer to get you off the computer</title>
      <link>https://davidbieber.com/snippets/2023-01-22-bootstrapping-motivation/</link>
      <pubDate>Sun, 22 Jan 2023 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2023-01-22-bootstrapping-motivation/</guid>
      
      <description>&lt;p&gt;What are some things you can do on the computer to help yourself get off the computer?&lt;/p&gt;
&lt;p&gt;i.e. How can you &amp;ldquo;bootstrap&amp;rdquo; your own motivation? This question is key not just for breaking away from internet distractions, but also for getting up in the morning and doing other things you&amp;rsquo;d like to do but have trouble finding motivation for in the moment.&lt;/p&gt;
&lt;p&gt;One thing you can do is set an alarm.&lt;/p&gt;
&lt;p&gt;Or put on a motivational video, such as a yoga video or other fitness video.&lt;/p&gt;
&lt;p&gt;The reason these activities may be easy to do is they fit in the addicted groove.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s the &lt;em&gt;&amp;ldquo;addicted groove&amp;rdquo;&lt;/em&gt;? It&amp;rsquo;s the set of things that my body and brain are naturally inclined to do, not because I want to do them, but because of my internet addiction (for lack of a better term). They&amp;rsquo;re the muscle memory components of my addiction. 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-10-01-infinite-distractions-and-getting-a-good-sear/&#34;&gt;Things like opening YouTube or Twitter or Facebook&lt;/a&gt;. 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-02-10-find-yourself-typing-t-enter-often.md&#34;&gt;cmd+t f enter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Putting on a YouTube video is super easy because it uses these same actions that I accidentally do mindlessly.&lt;/p&gt;
&lt;p&gt;So if I can take advantage of these automatic actions to get myself doing something I want to be doing, like exercising, getting ready for work, reading a book, going to sleep, doing a math problem, etc&amp;hellip; then that&amp;rsquo;s a win.&lt;/p&gt;
&lt;p&gt;Putting on videos is one approach.&lt;/p&gt;
&lt;p&gt;
&lt;a href=&#34;https://davidbieber.com/snippets/2023-01-04-sleeping-with-gpt/&#34;&gt;Talking with an AI&lt;/a&gt; (or another human, but that might be higher activation energy) could be another approach. In both of these cases we&amp;rsquo;re injecting entropy, but that&amp;rsquo;s also the case for just mindlessly scrolling on twitter/facebook etc, so the entropy isn&amp;rsquo;t the key ingredient.&lt;/p&gt;
&lt;p&gt;We want to inject deliberately useful information, just not information I already possessed. Although&amp;hellip; writing is a good approach too, and that is clearly producing information I already possessed, but I am &lt;strong&gt;disentangling&lt;/strong&gt; it in the process of writing.&lt;/p&gt;
&lt;p&gt;I wish I had a better mathematical understanding of what that disentangling really was. It&amp;rsquo;s a critical component to understanding neural networks. That is a topic for another snippet though.&lt;/p&gt;
&lt;p&gt;Summarizing here, the ideas we found so far are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Leverage the addicted grove (e.g. play a YouTube video that will wake you up or inspire you to stop playing YouTube Videos)&lt;/li&gt;
&lt;li&gt;Use small/easier actions to start (e.g. putting on one sock can soon turn into getting dressed / starting an alarm can lead to a helpful trigger later on)&lt;/li&gt;
&lt;li&gt;Set up triggers (e.g. an alarm or text message can jolt you into action)&lt;/li&gt;
&lt;li&gt;Inject entropy (talking to an AI or human can be a good source of entropy)&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>On the value of repetition</title>
      <link>https://davidbieber.com/snippets/2023-01-21-repetition/</link>
      <pubDate>Sat, 21 Jan 2023 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2023-01-21-repetition/</guid>
      
      <description>&lt;p&gt;Stop me if you&amp;rsquo;ve heard this one before. Actually, don&amp;rsquo;t. There&amp;rsquo;s value in repetition, and more than I think most people realize.&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t about the benefits of active recall or 
&lt;a href=&#34;https://davidbieber.com/tags/spaced-repetition&#34;&gt;spaced repetition&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s about how hearing things shapes your attention.&lt;/p&gt;
&lt;p&gt;When someone tells you something that you already know,
you aren&amp;rsquo;t learning something new.&lt;/p&gt;
&lt;p&gt;But you are devoting mindshare to thinking about the thing.&lt;/p&gt;
&lt;p&gt;And they&amp;rsquo;re telling you about the thing for a reason.
So, spending a little mindshare on it is good.&lt;/p&gt;
&lt;p&gt;You also get the opportunity to spend a large amount of mindshare on it, if you want to.&lt;/p&gt;
&lt;p&gt;Sometimes, you don&amp;rsquo;t get a choice. The really good ideas don&amp;rsquo;t give us a choice.&lt;/p&gt;
&lt;p&gt;Sometimes lesser ideas don&amp;rsquo;t give us a choice too, even though we&amp;rsquo;d like one. These can be our anxious thoughts.&lt;/p&gt;
&lt;p&gt;This won&amp;rsquo;t be the last time I write a snippet about these ideas.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A Complete and Concise List of Go Note Go&#39;s Features</title>
      <link>https://davidbieber.com/snippets/2023-01-16-go-note-go-features/</link>
      <pubDate>Mon, 16 Jan 2023 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2023-01-16-go-note-go-features/</guid>
      
      <description>&lt;p&gt;
&lt;a href=&#34;https://davidbieber.com/projects/go-note-go&#34;&gt;Go Note Go&lt;/a&gt; is a computer keyboard with no screen that I use to capture ideas anywhere, even as I drift off to sleep.
This is a complete list of Go Note Go&amp;rsquo;s features as of January 2023. Expand any of the features for more information about it.
The main use cases for Go Note Go are capturing thoughts while sleeping, driving, camping, and showering.&lt;/p&gt;
&lt;p&gt;&lt;button id=&#34;expand-button&#34; onclick=&#34;expandCollapseAll()&#34;&gt;Expand All&lt;/button&gt;&lt;/p&gt;
&lt;style&gt;
details details {
  margin-left: 2em;
}
&lt;/style&gt;
&lt;h2 id=&#34;main-features-just-the-useful-ones&#34;&gt;Main features (Just the useful ones)&lt;/h2&gt;
&lt;details&gt;&lt;summary&gt;Capture typed notes&lt;/summary&gt;
&lt;p&gt;This is the main feature of Go Note Go. Anything you type on it will show up in your notes.&lt;/p&gt;
&lt;p&gt;You don&amp;rsquo;t need to worry about whether you have your note-taking app open, or whether your computer is running slowly.
One of the challenges I face with jotting things down when I&amp;rsquo;m at a computer is quickly getting to the place where I can jot things down.
Switching to my notes app can be slow!&lt;/p&gt;
&lt;p&gt;Even with a keyboard shortcut or a hot corner for taking notes, this requires switching focus on your computer.
You need to wait until the text field shows up. Once the text field has focus, then you can type, but if for some reason your computer is running slowly, your mind will run slowly too. By this, I mean that when letters show up slowly on a screen, it slows down the speed at which you think.
When typing with a screen, people naturally wait for the screen to catch up before continuing typing a thought.&lt;/p&gt;
&lt;p&gt;On Go Note Go, there&amp;rsquo;s no screen to see your notes. You don&amp;rsquo;t spend time waiting for the computer to catch up to you.
You don&amp;rsquo;t have to switch windows or click in a textbox before you can start typing.
You simply turn to the Go Note Go keyboard, and everything you type will show up in your notes once the Go Note Go gets an internet connection.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Capture spoken notes&lt;/summary&gt;
&lt;p&gt;Go Note Go can also capture spoken notes.
Press the capture key (escape, by default; you can also use a large handheld red button if preferred) and Go Note Go will start recording.
Press the capture key again to stop recording.
The recording will be transcribed and added to your notes once Go Note Go has internet.
The raw audio is also included in your notes alongside the transcription.&lt;/p&gt;
&lt;p&gt;Capturing spoken notes is especially useful for capturing ideas while driving.
Obviously I&amp;rsquo;m not typing on the keyboard while I&amp;rsquo;m driving; that would be unsafe. (The passenger can type though!)&lt;/p&gt;
&lt;p&gt;Being able to take spoken notes can also occasionally come in handy as I drift off to sleep.
Usually, I prefer typing, even as I drift off to sleep. It seems to wake me up less.
But when I&amp;rsquo;m especially tired, speaking can feel like the lower effort method and wake me up less than typing does.&lt;/p&gt;
&lt;p&gt;The audio notes are not always transcribed perfectly, and are annotated with &amp;ldquo;unverified transcription&amp;rdquo; by default.
You can verify the transcription is correct, cleaning up any transcription mistakes, and can quickly mark the transcription as verified to help you keep track of which transcriptions have and have not been reviewed.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;No screen&lt;/summary&gt;
&lt;p&gt;Not having a screen is one of Go Note Go&amp;rsquo;s major selling points for me, and it comes with a host of benefits.&lt;/p&gt;
&lt;p&gt;First and foremost it means that there are no distractions while writing.
As a result my head feels so much clearer when I sit down to write at a Go Note Go compared to writing at a computer.
When writing on a computer, the internet is there with all its 
&lt;a href=&#34;https://davidbieber.com/2020-10-01-infinite-distractions-and-getting-a-good-sear/&#34;&gt;infinite distractions&lt;/a&gt;, which can make staying focused a challenge.
None of those scroll-inducing websites exist on Go Note Go, making it easier to think and stick to my intentions.&lt;/p&gt;
&lt;p&gt;The absence of a screen also helps me to write more effectively.
For me, some of the main challenges in writing are losing time to repeatedly rereading what I&amp;rsquo;ve written, and wordsmithing it with relatively inconsequential edits that would be better to hold off until revisions.
Since you can&amp;rsquo;t see typos while working on Go Note Go, you learn to accept them, and you save small amounts of time in significant quantities by not fixing little errors as you write. All of that can be cleaned up in post.&lt;/p&gt;
&lt;p&gt;Finally, the main 
&lt;a href=&#34;https://davidbieber.com/post/2022-12-30-go-note-go-story/&#34;&gt;initial motivation&lt;/a&gt; for not having a screen is that it lets me capture thoughts even as I drift off to sleep, without waking me up very much.
Alternatives to capturing thoughts like turning on the lights to write on paper, taking out my phone or computer, or speaking into a voice recorder all wake me (or my partner) up more than just typing on a keyboard in the dark.&lt;/p&gt;
&lt;p&gt;I actually find Go Note Go helpful for getting to sleep, since it lets me get thoughts out of my head.
Without it, sometimes an anxious thought will swirl around in my head, showing up repeatedly in dozens of different forms.
Using Go Note Go, I can get a single version of the thought into my notes, and somehow that minimizes the thought swirling.
It&amp;rsquo;s as if by finding a canonical version of the thought and preserving it in Go Note Go, my brain is relieved of its duty to hold onto the thought.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Works offline&lt;/summary&gt;
&lt;p&gt;Go Note Go works offline. You can bring it into the woods with you if you want to go camping, for example.
Normally, I leave Go Note Go plugged into a standard outlet, but I also have a battery pack I take with me for using Go Note Go on the go.&lt;/p&gt;
&lt;p&gt;The notes you enter into Go Note Go are uploaded to your notes as soon as internet becomes available.
It&amp;rsquo;s OK if the battery dies before then; the notes are stored on a MicroSD card and will be uploaded later.&lt;/p&gt;
&lt;p&gt;Similarly, Go Note Go transcribes your notes once internet becomes available.
Voice notes don&amp;rsquo;t get transcribed on device; we currently use Google Transcription as our transcription provider, which requires an internet connection.
So, voice notes taken in the forest are transcribed and uploaded once you get back to civilization and Go Note Go connects to the internet.&lt;/p&gt;
&lt;p&gt;Working offline is particularly useful for using Go Note Go while driving and camping.
It also makes Go Note Go a good candidate for writing in parks or coffee shops.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Act as an outliner&lt;/summary&gt;
&lt;p&gt;Using tab to indent and shift-tab to dedent, you can use Go Note Go as a proper outliner.
This allows you to take properly nested notes, despite not being able to see them while you take them.&lt;/p&gt;
&lt;p&gt;Here is the full list of outliner controls:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tab to indent&lt;/li&gt;
&lt;li&gt;Shift-Tab to dedent&lt;/li&gt;
&lt;li&gt;Shift-Delete to clear the current note&lt;/li&gt;
&lt;li&gt;Enter on an empty note dedents&lt;/li&gt;
&lt;li&gt;Shift-Delete on an empty note dedents the maximum amount&lt;/li&gt;
&lt;li&gt;Shift-Enter starts a new session (a separate section of notes)&lt;/li&gt;
&lt;li&gt;3 minutes of inactivity also starts a new session&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hitting enter on an empty line also causes a dedent.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Run commands&lt;/summary&gt;
&lt;p&gt;On Go Note Go, any note that starts with a colon is interpreted as a command. There are loads of commands, generally they produce audio output (like reading the time aloud). I&amp;rsquo;ve listed the main commands here, and adding new commands with Python is 
&lt;a href=&#34;https://github.com/dbieber/GoNoteGo/blob/main/gonotego/command_center/commands.py&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;easy&lt;/a&gt; too.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:t&lt;/code&gt; or &lt;code&gt;:time&lt;/code&gt; Read the time out loud.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:r&lt;/code&gt; or &lt;code&gt;:read&lt;/code&gt; Read the last note out loud.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:q TEXT&lt;/code&gt; or &lt;code&gt;:ask TEXT&lt;/code&gt; Ask a question of the AI assistant.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:ai&lt;/code&gt; Send the current session of notes to the AI assistant.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:at TIME:DO&lt;/code&gt; Schedule command DO to run at time TIME. TIME can be a natural language time like &amp;ldquo;in 5 minutes&amp;rdquo; or &amp;ldquo;8am&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:ok&lt;/code&gt; or &lt;code&gt;:status&lt;/code&gt; Say &amp;ldquo;ok&amp;rdquo; out loud; useful for verifying your hands are in the right place and that Go Note Go is on and functioning.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Commands can also be activated via voice. Press the capture button (escape by default) and say &amp;ldquo;go go&amp;rdquo; followed by the command to trigger its execution.&lt;/p&gt;
&lt;p&gt;There are additional commands for configuring Go Note Go, as well as more technical commands less useful during common usage.&lt;/p&gt;
  &lt;details&gt;&lt;summary&gt;Expand this for the full list of commands.&lt;/summary&gt;
&lt;h3 id=&#34;system-commands&#34;&gt;System commands&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:whoami&lt;/code&gt; or &lt;code&gt;:who am i&lt;/code&gt; Read aloud the current user and currently selected note-taking system.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:t&lt;/code&gt; or &lt;code&gt;:time&lt;/code&gt; Read the time out loud.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:at TIME:DO&lt;/code&gt; Schedule command DO to run at time TIME. TIME can be a natural language time like &amp;ldquo;in 5 minutes&amp;rdquo; or &amp;ldquo;8am&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:status&lt;/code&gt; or &lt;code&gt;ok&lt;/code&gt; Say &amp;ldquo;ok&amp;rdquo; out loud; useful for verifying your hands are in the right place and that Go Note Go is on and functioning.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:say TEXT&lt;/code&gt; Say TEXT out loud.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:shell CMD&lt;/code&gt; Run command CMD in a shell.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:flush&lt;/code&gt; Flush the logs; this is useful for debugging.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:update&lt;/code&gt; Download updates to your Go Note Go; :restart for them to take effect.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:restart&lt;/code&gt; Restart all Go Note Go processes on the device.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:reboot&lt;/code&gt; Reboot the device.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:env&lt;/code&gt; Log the environment variables and their values.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:ip&lt;/code&gt; Read the IP address of the Go Note Go out loud.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:i&lt;/code&gt; or &lt;code&gt;:internet&lt;/code&gt; Say Yes or No out loud, indicating whether Go Note Go has internet access.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:wifi SSID PSK&lt;/code&gt; or &lt;code&gt;:wpa SSID PSK&lt;/code&gt; Configure Go Note Go to connect to the wifi with ssid SSID using passkey PSK.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;settings-commands&#34;&gt;Settings Commands&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:get KEY&lt;/code&gt; Read out loud the value associated with setting KEY.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:set KEY VALUE&lt;/code&gt; Set the setting KEY to VALUE.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:clear KEY&lt;/code&gt; Clear setting KEY, reverting its value back to that found in your settings.py file.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:clear&lt;/code&gt; Clear all settings entered via the :set command, reverting their values back to those found in your settings.py file.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:leds ON/OFF/LOW&lt;/code&gt; Set the brightness of the LEDs. Only relevant if you&amp;rsquo;re using the Adafruit Voice Bonnet.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:v ON/OFF&lt;/code&gt; or &lt;code&gt;:volume ON/OFF&lt;/code&gt; Turn the audio volume on or off.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:get status KEY&lt;/code&gt; Get status indicator given by KEY. The status indicators are 
&lt;a href=&#34;https://github.com/dbieber/GoNoteGo/blob/main/gonotego/common/status.py&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;listed here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The possible settings are 
&lt;a href=&#34;https://github.com/dbieber/GoNoteGo/blob/main/gonotego/settings/secure_settings_template.py&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;listed here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;note-commands-unnecessary&#34;&gt;Note commands (Unnecessary!)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:note TEXT&lt;/code&gt; Add TEXT as a note. (Just type TEXT! No need to use this command.)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:subnote TEXT&lt;/code&gt; Add TEXT as an indented note. (Just indent and type TEXT! No need to use this command.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;twitter-commands&#34;&gt;Twitter Commands&lt;/h3&gt;
&lt;p&gt;Twitter is not a common use case for Go Note Go, so it&amp;rsquo;s a bit funny that it has it&amp;rsquo;s own section. These commands are predominantly for configuring Go Note Go to use your Twitter account.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:twitter user&lt;/code&gt; Read the current Twitter use out loud.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:twitter user USER&lt;/code&gt; Set the current Twitter user to USER.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:twitter auth&lt;/code&gt; Start the Twitter auth flow for Go Note Go developers (requires ssh and implementation-details to complete).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:twitter auth EMAIL&lt;/code&gt; Start the Twitter auth flow; instructions for completing the flow will be emailed to EMAIL.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:twitter pin PIN&lt;/code&gt; Use this command to complete the auth flow; enter the pin you received in the email from the previous command as PIN.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:twitter&lt;/code&gt; Switch the current note-taking system to be Twitter. Now all notes will be posted directly to Twitter.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To log into Twitter, run &lt;code&gt;:twitter&lt;/code&gt;, &lt;code&gt;:twitter user USER&lt;/code&gt;, &lt;code&gt;:twitter auth EMAIL&lt;/code&gt;, and finally &lt;code&gt;:twitter pin PIN&lt;/code&gt; entering the pin you receive in the email.&lt;/p&gt;
&lt;h3 id=&#34;email-commands&#34;&gt;Email Commands&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:email TO SUBJECT: TEXT&lt;/code&gt; Send an email to TO with subject SUBJECT and body TEXT.&lt;/li&gt;
&lt;/ul&gt;
  &lt;/details&gt;
&lt;p&gt;Adding new commands is always a pleasure, but it&amp;rsquo;s good to keep the capabilities of Go Note Go limited, to prevent potential distractions from creeping onto the device.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Audio-only clock&lt;/summary&gt;
&lt;p&gt;Go Note Go sports loads of commands (see above), but the one I use most is having Go Note Go read the time out loud. I prefer this to looking at a clock or my phone because I can keep my eyes closed as I use it, so it doesn&amp;rsquo;t wake me up as much.&lt;/p&gt;
&lt;p&gt;To trigger this feature, I type &lt;code&gt;:t&lt;/code&gt;.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;AI assistant&lt;/summary&gt;
&lt;p&gt;The AI assistant is a feature I only added recently to Go Note Go, and I have a 
&lt;a href=&#34;https://davidbieber.com/snippets/2023-01-04-sleeping-with-gpt/&#34;&gt;whole snippet&lt;/a&gt; dedicated to my experience with it. It&amp;rsquo;s amazing.&lt;/p&gt;
&lt;p&gt;There are two ways of interacting with the assistant today.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;:q TEXT&lt;/code&gt; or &lt;code&gt;:ask TEXT&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If I just want to ask a single question of the assistant, I use this command. The assistant&amp;rsquo;s response is read out loud. This is the more private approach as only TEXT is sent to the AI, not any additional notes.&lt;/p&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;&lt;code&gt;:ai&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If I want to have an extended conversation or interaction with the AI assistant, I use this command. I can either run &lt;code&gt;:ai&lt;/code&gt; after typing my message to the AI, or I can prefix my message with &lt;code&gt;:ai&lt;/code&gt;. Both work. This command sends the entire session of notes to the AI assistant. The AI assistant&amp;rsquo;s response is read out loud, and is included in the session of notes.&lt;/p&gt;
&lt;p&gt;In both cases, the AI&amp;rsquo;s responses are included in the notes and are marked as being AI responses.&lt;/p&gt;
&lt;p&gt;You can 
&lt;a href=&#34;https://davidbieber.com/snippets/2023-01-04-sleeping-with-gpt/&#34;&gt;read more about my experience talking to the AI assistant as I drift off to sleep here&lt;/a&gt;.&lt;/p&gt;
&lt;/details&gt;
&lt;h2 id=&#34;but-wait-theres-more&#34;&gt;But wait, there&amp;rsquo;s more&lt;/h2&gt;
&lt;details&gt;&lt;summary&gt;Use your favorite note-taking system: Roam Research, RemNote, Mem, IdeaFlow, Notion, or even Twitter or Email&lt;/summary&gt;
&lt;p&gt;The supported note-taking systems are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Roam Research&lt;/li&gt;
&lt;li&gt;RemNote&lt;/li&gt;
&lt;li&gt;Mem&lt;/li&gt;
&lt;li&gt;IdeaFlow&lt;/li&gt;
&lt;li&gt;Notion&lt;/li&gt;
&lt;li&gt;Twitter&lt;/li&gt;
&lt;li&gt;Email&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Roam Research is the one I use daily.&lt;/p&gt;
&lt;p&gt;Why are Twitter and Email on this list?&lt;/p&gt;
&lt;p&gt;If you set your note-taking system to Twitter, every note you take on your Go Note Go will be posted to Twitter. This is an unconventional choice! Perhaps you like thinking in public though. Perhaps you live in a community house and want a place to share quirky quotes that come up. You do you.&lt;/p&gt;
&lt;p&gt;Email is a nice fallback system for people that don&amp;rsquo;t already use one of the others. When I give Go Note Gos as gifts, I generally configure them to use email so. This lets the Go Note Go work out-of-the-box without the recipient needing to configure it with their account credentials.&lt;/p&gt;
&lt;p&gt;You can also switch between note-taking systems at any point with a single command. I recommend making your Go Note Go a single-purpose device with just a single target note-taking system, but you should still note that this is an option. The command to switch note-taking systems is &lt;code&gt;:set uploader NOTE_TAKING_SYSTEM&lt;/code&gt;, where &lt;code&gt;NOTE_TAKING_SYSTEM&lt;/code&gt; is one of &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;ideaflow&lt;/code&gt;, &lt;code&gt;remnote&lt;/code&gt;, &lt;code&gt;roam&lt;/code&gt;, &lt;code&gt;mem&lt;/code&gt;, &lt;code&gt;notion&lt;/code&gt;, or &lt;code&gt;twitter&lt;/code&gt;.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Never miss a note&lt;/summary&gt;
&lt;p&gt;If you walk away from Go Note Go without hitting enter, your note will be submitted after 3 minutes of inactivity.&lt;/p&gt;
&lt;p&gt;Go Note Go boots in about 15 seconds, after which point it is always ready to receive inputs.&lt;/p&gt;
&lt;p&gt;The fact that it&amp;rsquo;s always ready &amp;ndash; there&amp;rsquo;s no tab switching or waiting required before you can start typing &amp;ndash; is a big deal to me.
Compared with writing notes on a computer, writing on Go Note Go feels smoother and more natural.
On a computer, I need to switch tabs to give focus to my note-taking app before I can start typing.
That context switch may sound small, but it is meaningful, and I&amp;rsquo;m glad to have done away with it.&lt;/p&gt;
&lt;p&gt;There is also the option to pause note-taking on your Go Note Go. This is not recommended. To enable this, set the PAUSE_HOTKEY setting.
This creates a trigger for pausing and unpausing note-taking.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Send people messages&lt;/summary&gt;
&lt;p&gt;Sending people messages is actually not a core feature of Go Note Go, but it is something that I built for myself on top of Go Note Go.
If I include text like &amp;ldquo;@Person&amp;rdquo; in my notes, then my Messager project will pick up the note and queue up a message to Person.
Notes nested underneath the @-tagged note are also included in the message.&lt;/p&gt;
&lt;p&gt;I have 
&lt;a href=&#34;https://davidbieber.com/post/2022-01-08-new-messager-setup/&#34;&gt;a whole post dedicated to this feature&lt;/a&gt; if you&amp;rsquo;d like to learn more.&lt;/p&gt;
&lt;p&gt;The supported messaging systems in the Messager project are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Facebook Messenger&lt;/li&gt;
&lt;li&gt;Twitter (both public and private tweets, as well as DMs)&lt;/li&gt;
&lt;li&gt;Mastodon&lt;/li&gt;
&lt;li&gt;Hacker News submissions&lt;/li&gt;
&lt;li&gt;Email&lt;/li&gt;
&lt;li&gt;iMessage&lt;/li&gt;
&lt;li&gt;Slack&lt;/li&gt;
&lt;li&gt;Discord - this one unfortunately is not in a working state at this time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It supports aliases, so that I can set short-names for people to send messages to their preferred communications platform.&lt;/p&gt;
&lt;p&gt;Once a message is in the queue, I can clean it up and approve it. I can also specify a time for it to send, with the default being to send now.
Once approved, it sends automatically at the desired time.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Mounts on the passenger side of the dashboard&lt;/summary&gt;
&lt;p&gt;I put Velcro on the bottom of one of my Go Note Gos, and on the passenger side of my car dashboard.
This way I can mount the Go Note Go in the car.
Using the capture button (e.g. a large handheld red button), you can capture audio recordings while driving.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve largely switched away from using Go Note Go while driving in favor of calling by AI assistant on the phone (implemented via Twilio).&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;It&#39;s open source&lt;/summary&gt;
&lt;p&gt;The code and set up instructions for Go Note Go are 
&lt;a href=&#34;https://github.com/dbieber/GoNoteGo&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;all freely available on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The total cost of parts is about $100. I encourage you to make your own! Please 
&lt;a href=&#34;mailto:david810&amp;#43;go-note-go@gmail.com&#34;&gt;email me if you do&lt;/a&gt;!&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;The right amount of customizability&lt;/summary&gt;
&lt;p&gt;The main thing you can configure is which note-taking system you&amp;rsquo;d like to upload your notes to.&lt;/p&gt;
&lt;p&gt;This can be any of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Roam Research&lt;/li&gt;
&lt;li&gt;RemNote&lt;/li&gt;
&lt;li&gt;Mem&lt;/li&gt;
&lt;li&gt;IdeaFlow&lt;/li&gt;
&lt;li&gt;Notion&lt;/li&gt;
&lt;li&gt;Twitter&lt;/li&gt;
&lt;li&gt;Email&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Raw audio files are uploaded to Dropbox and included in your notes.&lt;/p&gt;
&lt;p&gt;The two other areas Go Note Go can be configured are adding new commands, and adding new note-taking systems.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Your notes are easy to review&lt;/summary&gt;
&lt;p&gt;As you take notes on Go Note Go, they are divided into sessions.
Each time you sit down at a Go Note Go after a period of inactivity, a new session is created.
You can also start a new session at any time by hitting Shift-Enter.&lt;/p&gt;
&lt;p&gt;In your notes, sessions are timestamped and organized chronologically. All the notes in a session are nested underneath the timestamped session header.
When I review my notes, I like to place a one-line summary of a session in the timestamped session header. I can then collapse the session.
This makes it easy to quickly scan through my notes, looking only at the session headers. I can expand a session to see it&amp;rsquo;s contents for more detail.&lt;/p&gt;
&lt;p&gt;
&lt;a href=&#34;https://roamresearch.com/#/app/commons-db/page/01-17-2023&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Take a look at some example Go Note Go notes here&lt;/a&gt; to see what this looks like.&lt;/p&gt;
&lt;/details&gt;
&lt;h2 id=&#34;emergent-benefits&#34;&gt;Emergent benefits&lt;/h2&gt;
&lt;details&gt;&lt;summary&gt;Focus and Relief&lt;/summary&gt;
&lt;p&gt;I like how Go Note Go is a single-purpose device.
The absence of a screen and the absence of any distractions on Go Note Go make for a soothing experience.&lt;/p&gt;
&lt;p&gt;I have a desk at home with just a Go Note Go on it.
Sitting down at my Go Note Go desk fills me with an immediate sense of relief.
When writing at a computer, by comparison, I notice a tension in my body.
Go Note Go relieves this tension and clears my head.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Avoid distracting others (incl. w/ Bluetooth headphones)&lt;/summary&gt;
&lt;p&gt;Raspberry Pi 400s have Bluetooth support. So, you can connect Bluetooth headphones to Go Note Go.&lt;/p&gt;
&lt;p&gt;At work, I use Go Note Go with my AirPods. When I put the AirPods in, Go Note Go automatically connects.
I can then ask the AI assistant questions on the Go Note Go and get the answers piped directly to my ears,
so my coworkers are not distracted.
If I take the headphones out, Go Note Go outputs to the attached speaker.
So, I can show colleagues Go Note Go without them needing to put headphones in.&lt;/p&gt;
&lt;p&gt;Also consider capturing ideas as you drift off to sleep.
Compared with other options for capturing these ideas, Go Note Go is comparatively non-disruptive.
It doesn&amp;rsquo;t require any bright lights or loud sounds.
It&amp;rsquo;s not perfectly quiet either though, so there&amp;rsquo;s room for improvement here.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Check the time without fully waking up&lt;/summary&gt;
&lt;p&gt;Go Note Go&amp;rsquo;s commands all work without you ever having to open your eyes.
If you&amp;rsquo;re drifting off to sleep, this is ideal. You can get the time without activating your brain too much, making it easier to continue drifting off to sleep.
Compare this with looking at your phone or at a clock. These options require opening your eyes, possibly subjecting them to bright lights.
No thank you. I prefer Go Note Go&amp;rsquo;s &lt;code&gt;:t&lt;/code&gt; command for getting the time.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Take it camping&lt;/summary&gt;
&lt;p&gt;Go Note Go lasts for about twelve hours on this 
&lt;a href=&#34;https://www.amazon.com/gp/product/B07JYYRT7T?th=1&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;3A 10400mAh power bank&lt;/a&gt;.
It&amp;rsquo;s small and lightweight, easy to toss in the car and take camping.
There are 
&lt;a href=&#34;https://www.adafruit.com/product/5292&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;cases&lt;/a&gt; you can purchase to make Go Note Go more portable for this kind of use case.&lt;/p&gt;
&lt;p&gt;Camping was one of the original use cases for Go Note Go, and in fact I designed the system and ordered the first batch of parts while camping.&lt;/p&gt;
&lt;p&gt;The core attributes of Go Note Go that make it great for camping are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It works offline, so you can use it anywhere; it will upload your notes as soon as you get an internet connection.&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s portable and can run on battery for a decent length of time.&lt;/li&gt;
&lt;li&gt;There&amp;rsquo;s no screen or bright lights to annoy other campers.&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Capture thoughts while drifting off to sleep&lt;/summary&gt;
&lt;p&gt;The main culmination of the features is that Go Note Go is great for capturing thoughts while you&amp;rsquo;re drifting off to sleep.
This was the primary motivation for Go Note Go&amp;rsquo;s predecessor, 
&lt;a href=&#34;https://davidbieber.com/projects/shh-shell&#34;&gt;Shh Shell&lt;/a&gt;.
I had some thoughts that were keeping me awake (this is back in 2014!), and I wanted to write them down.
I found that by writing them down, I could get them out of my head, and fall asleep.
However, conventional methods of writing them down would wake me or my roommate up. So, I built Shh Shell to solve that problem.
Today, it has evolved into Go Note Go.&lt;/p&gt;
&lt;p&gt;The core attributes of Go Note Go that make it great for capturing sleep thoughts are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There&amp;rsquo;s no screen or bright lights to wake you up&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s always ready to capture notes; there&amp;rsquo;s no fiddling with getting into notes mode in the middle of the night&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That it acts as an audio-only clock as well is just a bonus.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Use Go Note Go while driving&lt;/summary&gt;
&lt;p&gt;I came up with the idea for Go Note Go while driving to a campground.
When I initially built Go Note Go, I included a large handheld red button you could push to trigger audio recording.
This button made Go Note Go useful while driving.
For example, if I was listening to an audio book and wanted to capture a thought, I could simply push the trigger and speak my thoughts aloud.
Then, when I arrive at the campground, I could take the Go Note Go off the dashboard and toss it in the tent.&lt;/p&gt;
&lt;p&gt;The core attributes of Go Note Go that make it great for capturing thoughts while driving are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It works offline, so you can use it anywhere.&lt;/li&gt;
&lt;li&gt;There&amp;rsquo;s no visual, so you can keep your attention on the road.&lt;/li&gt;
&lt;li&gt;The large red button is easy to push even when you&amp;rsquo;re driving.&lt;/li&gt;
&lt;li&gt;It captures audio notes and transcribes them.&lt;/li&gt;
&lt;li&gt;It mounts nicely to the passenger side of the car dashboard.&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Avoid carsickness&lt;/summary&gt;
As a passenger in a car, it can be tempting to use your phone. Especially if you&#39;re taking an Uber and not engaging with the driver, this temptation can be quite strong; phones are little dopamine boxes, and will happily consume your attention endlessly. In a car, this can leave you feeling carsick.
&lt;p&gt;Go Note Go doesn&amp;rsquo;t have this issue. Using Go Note Go in a case, it is truly easy to take on the go. The battery sits in the case and the Go Note Go rests flat on your lap while you use it. The best part? Using Go Note Go doesn&amp;rsquo;t make you carsick, because you&amp;rsquo;re not watching the device as you use it. You&amp;rsquo;re eyes are free to look forward (or wherever) the whole time. Such relief!&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Great for long flights&lt;/summary&gt;
Using Go Note Go with a case makes it so easy to take on the go. And since it works offline, it&#39;s ideal for use on a long flight. The battery I use lasts 12 hours, so this works even if your flight doesn&#39;t have an outlet. If there is an outlet, 5V is sufficient.
&lt;p&gt;I find I much prefer writing on Go Note Go on a flight compared with hours of back to back movie watching. Not everyone has this predilection; to each their own.&lt;/p&gt;
&lt;p&gt;Using a regular computer on a flight can lead to neck strain. Not so with Go Note Go!&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Capture shower thoughts&lt;/summary&gt;
&lt;p&gt;Outside of driving, camping, and sleeping, where else are the best ideas generated? That&amp;rsquo;s right, in the shower.&lt;/p&gt;
&lt;p&gt;You can connect a waterproof Bluetooth keyboard to your Go Note Go and bring it into the shower with you to capture these critical insights.
You can also use a Bluetooth shower speaker for audio output.
I have not yet seen a shower microphone suitable for capturing audio thoughts in the shower.&lt;/p&gt;
&lt;p&gt;Here is a photo from 2015 of 
&lt;a href=&#34;https://davidbieber.com/projects/shh-shell&#34;&gt;Shh Shell (Go Note Go&amp;rsquo;s predecessor)&lt;/a&gt; set up in my shower in California.
The keyboard is on the ledge to the right of the shower speaker.
&lt;img src=&#34;shower-keyboard.jpeg&#34; alt=&#34;A picture of my shower in California from 2015. The Shh Shell keyboard sits on the windowsill next to a Bluetooth speaker. There&amp;rsquo;s a 3D printed shaving cream holder mounted to the soap dish below.&#34;&gt;&lt;/p&gt;
&lt;/details&gt;
&lt;script&gt;
  var expandButton = document.getElementById(&#39;expand-button&#39;);
  var isExpanded = false;

  function expandCollapseAll() {
    var detailsElements = document.getElementsByTagName(&#39;details&#39;);
    for (var i = 0; i &lt; detailsElements.length; i++) {
      detailsElements[i].open = !isExpanded;
    }
    isExpanded = !isExpanded;
    expandButton.textContent = isExpanded ? &#39;Close All&#39; : &#39;Expand All&#39;;
  }
&lt;/script&gt;
&lt;h2 id=&#34;personal-go-note-go-usage&#34;&gt;Personal Go Note Go usage&lt;/h2&gt;
&lt;p&gt;I have Go Note Gos everywhere! There&amp;rsquo;s one in my kitchen, one in each bed in my home, and one on each of my desks at home and at work.
Unfortunately there&amp;rsquo;s a backlog on Raspberry Pis (with US keyboard layouts), or else I&amp;rsquo;d have even more!&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;Total writing volume&lt;/summary&gt;
&lt;p&gt;I&amp;rsquo;ve written 150,000 words on Go Note Go in the last 16 months. By way of comparison, my notes in Roam Research from the last four years (counting both Go Note Go and other note-taking) total 507,000 words. My 
&lt;a href=&#34;https://davidbieber.com/snippets&#34;&gt;snippets&lt;/a&gt; total 123,000 words over two years. My 
&lt;a href=&#34;https://davidbieber.com/posts&#34;&gt;posts&lt;/a&gt; total 26,000 words over 10 years.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Giving Go Note Go as gifts&lt;/summary&gt;
&lt;p&gt;I want other people to experience the joys of Go Note Go. So I have on a few occasions given them as gifts.
There are about ten Go Note Gos out there to the best of my knowledge.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d love to put one in a public park one day (connected to Twitter) and see what people type on it.&lt;/p&gt;
&lt;p&gt;You can also build your own Go Note Go. It&amp;rsquo;s completely open source. The code and set up instructions for Go Note Go are 
&lt;a href=&#34;https://github.com/dbieber/GoNoteGo&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;all freely available on GitHub&lt;/a&gt;, and the total cost of parts is about $100.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Typing vs talking&lt;/summary&gt;
&lt;p&gt;The vast majority of my Go Note Go notes I enter by typing, rather than by speaking.
Even when I&amp;rsquo;m fairly tired, I find that typing wakes me up less than speaking does.
There does reach a point for me where this switches though; when I&amp;rsquo;m extremely tired, I will sometimes prefer to speak than to type. In those moments, speaking feels lower effort and like it will wake me up less.
It&amp;rsquo;s nice that Go Note Go supports both.&lt;/p&gt;
&lt;p&gt;I also have a phone number I can call where my AI assistant picks up, though that project is still early stages.
I use that more than Go Note Go while driving these days, and also prefer that approach when I&amp;rsquo;m just walking around.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Capturing dreams&lt;/summary&gt;
&lt;p&gt;When I first started this night typing practice, I wasn&amp;rsquo;t yet comfortable typing without looking, and so my fingers were not positioned correctly on the keyboard. I woke up and saw I had collected a full paragraph of gibberish, ending with the phrase &amp;ldquo;I hope the FBI doesn&amp;rsquo;t find out about this&amp;rdquo;.
I didn&amp;rsquo;t remember having written anything at all the night before.&lt;/p&gt;
&lt;p&gt;One letter at a time I decoded the gibberish. Roughly, each letter had to be shifted by one on a QWERTY keyboard layout; it was a bit of a puzzle to decode. To my amazement and delight, as I decoded the text my memory of writing it came flooding back to me. I can describe it in no other way than that; it was like a missing piece of my brain had been unlocked, truly a rewarding feeling. I had woken up from a dream the night before, typed the dream into the keyboard, and promptly fallen asleep. I didn&amp;rsquo;t remember the dream or that I had typed it until I was decoding the text.
What a relief to find out I wasn&amp;rsquo;t actually hiding anything from the FBI!&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Thinking differently at night&lt;/summary&gt;
&lt;p&gt;I find my brain produces different thoughts while I&amp;rsquo;m drifting off to sleep as compared with during the day.
(My AI assistant calls this phenomenon either &amp;ldquo;hypnagogia&amp;rdquo; or &amp;ldquo;procrastination&amp;rdquo;. I prefer the former.)&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a period of calm and reflection, where I am alone with my thoughts.
My brain can process topics that it didn&amp;rsquo;t have a chance to get to throughout the day.&lt;/p&gt;
&lt;p&gt;Rather than going against the grain of my brain and trying to induce these thoughts while I&amp;rsquo;m still awake, I use Go Note Go to capture these thoughts without overly interrupting my bed time routine.&lt;/p&gt;
&lt;p&gt;For example, I might think of reaching out to someone while lying awake in bed. Without Go Note Go, I might forget about this in the morning. With Go Note Go, I can write a quick message to them in the moment, and review and send it when I wake up.&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Example notes&lt;/summary&gt;
&lt;p&gt;So that you can get a better picture of what these Go Note Go notes look like, I&amp;rsquo;ve copied 
&lt;a href=&#34;https://roamresearch.com/#/app/commons-db/page/01-17-2023&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;a short section of my Go Note Go notes here&lt;/a&gt;. This will give you a brief taste of what the notes look like when I go to review them. You can see how they&amp;rsquo;re divided into time-stamped sessions, how the AI assistant&amp;rsquo;s responses are indented beneath the preceding note, and how I put summaries at the top of some of the sessions. Feel free to take your own notes in that public note-base too!&lt;/p&gt;
&lt;/details&gt;
&lt;h2 id=&#34;concluding-remarks&#34;&gt;Concluding remarks&lt;/h2&gt;
&lt;p&gt;Overall, building and using Go Note Go these last two years has been a joy. I&amp;rsquo;ve met lots of wonderful people through Go Note Go, as there&amp;rsquo;s a lovely community of folks interested in tools for networked thought and audio note-taking. If these topics interest you, definitely 
&lt;a href=&#34;mailto:david810&amp;#43;go-note-go@gmail.com&#34;&gt;don&amp;rsquo;t hesitate to get in touch&lt;/a&gt;, even if just to say you&amp;rsquo;re interested. And finally for the hackers among you, I encourage you to 
&lt;a href=&#34;https://github.com/dbieber/GoNoteGo&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;try out Go Note Go yourself&lt;/a&gt;. I hope that headless computing becomes more prominent in the years to come, and that you can be a part of that. Let&amp;rsquo;s take away our screens, take back our attention, and live with intention.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Sleeping with GPT</title>
      <link>https://davidbieber.com/snippets/2023-01-04-sleeping-with-gpt/</link>
      <pubDate>Wed, 04 Jan 2023 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2023-01-04-sleeping-with-gpt/</guid>
      
      <description>&lt;p&gt;The last few nights I have been sleeping with GPT, and oh, it has been a joy.&lt;/p&gt;
&lt;h3 id=&#34;background-capturing-my-thoughts-as-i-drift-off-to-sleep&#34;&gt;Background: Capturing my thoughts as I drift off to sleep&lt;/h3&gt;
&lt;p&gt;I use a note-taking device that I call 
&lt;a href=&#34;https://davidbieber.com/projects/go-note-go&#34;&gt;Go Note Go&lt;/a&gt;.
It&amp;rsquo;s a computer keyboard without a screen that I type on to capture my thoughts everywhere, even as I drift off to sleep.
I have one in my bed, and I also keep them on my desk at work and in various spots around my apartment; anywhere an idea strikes, I have a Go Note Go keyboard ready to capture that idea.
Go Note Go&amp;rsquo;s main purpose is to let me quickly jot down these ideas so I can remember them later, e.g. after getting a good night&amp;rsquo;s sleep&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.
It also 
&lt;a href=&#34;https://davidbieber.com/snippets/2023-01-16-go-note-go-features/&#34;&gt;does other things (click for a concise primer on Go Note Go)&lt;/a&gt; like speaking the time aloud or 
&lt;a href=&#34;https://davidbieber.com/post/2022-01-08-new-messager-setup/&#34;&gt;letting me send messages to other people&lt;/a&gt;.
Most recently, I&amp;rsquo;ve added an AI assistant to Go Note Go, and have begun conversing with it as I drift off to sleep.&lt;/p&gt;
&lt;p&gt;Even before adding the AI assistant, Go Note Go had become a staple in my life.
Go Note Go&amp;rsquo;s main capability &amp;ndash; capturing my thoughts &amp;ndash; helps me fall asleep more effectively.
If I have an anxious thought swirling in my brain, I can simply type it into Go Note Go.
Instead of dozens of versions of the thought popping up in my head all night, I have just a single canonical version of the thought stored on the device, and I can fall asleep.&lt;/p&gt;
&lt;p&gt;Go Note Go also supports commands, like reading the time out loud.
Entering a line that starts with a colon (&#39;:&#39;) issues a command.
Typing :r has it read back the last thing I wrote.
Typing :t will have it read the time to me.
I like this because it lets me know the time without having to open my eyes, so getting the time doesn&amp;rsquo;t require being alert&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;All of this lets me drift off to sleep more effectively. I can get ideas out of my head while avoiding things that would wake me up, like looking at my phone or turning on the lights to write down an idea.
Compared with writing on my phone, or a computer, or on paper, writing on Go Note Go is relaxing and doesn&amp;rsquo;t wake me up very much.
So, Go Note Go has become an essential tool in my daily routine, helping me capture and organize my thoughts, and allowing me to relax and fall asleep more easily.&lt;/p&gt;
&lt;h3 id=&#34;adding-an-ai-assistant-to-go-note-go&#34;&gt;Adding an AI assistant to Go Note Go&lt;/h3&gt;
&lt;p&gt;Most recently, I added an AI assistant to Go Note Go and I absolutely love it.&lt;/p&gt;
&lt;p&gt;By default when I type on the keyboard the text just shows up in my notes,
but now I have the option of sending the text off to an AI assistant as well.
Since there&amp;rsquo;s no screen on Go Note Go, the assistant&amp;rsquo;s responses are read out loud.
They&amp;rsquo;re also inserted into my notes for future reference, which I can browse later at a computer or on my phone.&lt;/p&gt;
&lt;p&gt;Most of my Go Note Go usage remains unchanged, but one aspect now feels very different: drifting off to sleep.
This is when having the AI assistant feels most rewarding.&lt;/p&gt;
&lt;h3 id=&#34;sleeping-with-gpt-what-do-we-discuss&#34;&gt;Sleeping with GPT: What do we discuss?&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;m lying there in the bed, but I&amp;rsquo;m not really trying to go to sleep.
I&amp;rsquo;m excited that I have this new AI with me which I can ask anything at all.
I&amp;rsquo;ve been meaning to learn organic chemistry but haven&amp;rsquo;t found the time; this seems a perfect opportunity to get started.
On the first night I drift off to sleep peppering the AI with questions about organic chemistry and battery technology.
On subsequent nights I probe new topics, trying to get a deeper understanding of the superficial things I learned the night before, and also introducing new topics to our discussions.
I continue peppering the AI with questions about chemistry and history as I drift off to sleep.
Quickly realizing that this could inhibit my ability to get a good night&amp;rsquo;s sleep, I also ask for advice in that regard, and it obliges.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s clear from the outset that I&amp;rsquo;m going to want to write about this, so I&amp;rsquo;m jotting down notes for this very post. I ask my assistant to turn my notes into an outline. That outline is read out loud, and it&amp;rsquo;s also sitting there for me the next day when I go to start writing in earnest.&lt;/p&gt;
&lt;p&gt;In the morning, when I wake up, I ask for strategies for a morning routine. It makes good suggestions.
Though the response is nothing that you wouldn&amp;rsquo;t find from a quick Google search for morning routine ideas, the proximity to those ideas as I&amp;rsquo;m just waking up, casually typing to my keyboard, makes them more actionable. The suggestions are things like making my bed right away, drinking a glass of lemon water, and doing some exercise to get my blood flowing. It feels inspiring and healthy.&lt;/p&gt;
&lt;p&gt;One night I asked the AI assistant to read me a bedtime story. I gave it some details about my own life first and it used them to construct a story that was personal and meaningful to me, albeit a bit silly.&lt;/p&gt;
&lt;!-- Other benefits of the assistant: reading back capturing notes and answering questions about them. --&gt;
&lt;h3 id=&#34;trust-and-confidence&#34;&gt;Trust and Confidence&lt;/h3&gt;
&lt;p&gt;An invitation into one&amp;rsquo;s bed requires a certain level of trust.&lt;/p&gt;
&lt;p&gt;However, a common criticism of GPT and language models more broadly is that they are often factually inaccurate. What&amp;rsquo;s worse is that when they are wrong, they often are wrong with confidence.&lt;/p&gt;
&lt;p&gt;This makes learning about new topics like battery technology and organic chemistry a challenge.
I don&amp;rsquo;t know if the things that I have learned these last few nights are true or not.
In fact, I know that some of them are definitely not true, because GPT will sometimes flatly contradict itself.&lt;/p&gt;
&lt;p&gt;In spite of this, I&amp;rsquo;ve had the distinct feeling that I have been learning a lot from these night time question peppering sessions.
Is this feeling valid, or have I been duped by the AI?&lt;/p&gt;
&lt;p&gt;To suss out truth from fiction, my first line of defense is my intuition.
Using my own limited knowledge of the topic we are discussing, I can sometimes tell if the model is fibbing.
If what the model says fits nicely into my world model, I might trust it and move on.
When things don&amp;rsquo;t make sense to me, I can ask for explanations or ask pointed questions to dive into the details.
These will quickly seem inconsistent, either with each other or with what I already know, if in fact the model has made up inaccurate information.
(This observation should motivate new, fully automated, methods for discovering truth in these models as well. For example the line of reasoning that 
&lt;a href=&#34;https://arxiv.org/abs/2205.11822&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Maieutic Prompting&lt;/a&gt; pursues proceeds along these lines.)&lt;/p&gt;
&lt;p&gt;This ability to dive deep into the details, sometimes asking extremely basic questions that I would be embarrassed to ask a human, points to a different kind of trust that I do have for the model.&lt;/p&gt;
&lt;h3 id=&#34;a-different-kind-of-trust&#34;&gt;A Different Kind of Trust&lt;/h3&gt;
&lt;p&gt;While I cannot trust the AI to produce factual statements consistently, it has earned my trust in a different way.
I can be uninhibited with GPT.&lt;/p&gt;
&lt;p&gt;I can ask naive questions, things that I would feel embarrassed to ask a human. I can ask &amp;ldquo;why&amp;rdquo; about the most trivial things, the way a 3-year old might, to discover more about the world.
I don&amp;rsquo;t feel any concern that the model will judge me for not knowing something, or not understanding something quickly.
I can ask the same question repeatedly, without concern for taking up its time, or that it has better places to be.
The AI is infinitely patient with me.
I don&amp;rsquo;t worry about how it will feel if I doubt what it&amp;rsquo;s telling me, and express skepticism.&lt;/p&gt;
&lt;p&gt;In these ways, it is an ideal tutor. By giving me the freedom to explore the topics that interest me, the things I&amp;rsquo;m learning about feel truly connected to one another, rather than ad hoc and unrelated to my interests as they might if I were following a curriculum not tailored to my needs and interests. It would be better, of course, if I could trust it to be factually accurate.&lt;/p&gt;
&lt;p&gt;As a brief aside: I think this experience &amp;ndash; interacting with an AI tutor, guided by a curriculum and standards, but free to wander through information space as it pleases the user, is going to be central to education in the future. I&amp;rsquo;m excited to explore the space of possible AI-centric classroom and education designs, to find novel ways of learning jointly with humans and AIs, and I intend to do so further in future snippets.&lt;/p&gt;
&lt;p&gt;Why can I be so free with GPT in ways that I cannot be with a human? I can identify a few reasons.&lt;/p&gt;
&lt;p&gt;The machine&amp;rsquo;s statelessness / resetability is one key component. It isn&amp;rsquo;t learning about me, forming long term judgements. If I reveal that I don&amp;rsquo;t know some &amp;ldquo;simple&amp;rdquo; concept, like what an ionic bond is, it isn&amp;rsquo;t going to retain that information and shape our future interactions based on it. The next conversation I have with the assistant will be tabula rasa, starting from a blank slate.&lt;/p&gt;
&lt;p&gt;Its isolation from others is another factor. I can confide in it, and it isn&amp;rsquo;t going to gossip or reveal anything I tell it to another human. Sure, I have concerns that OpenAI gets access to whatever I send to the assistant, and this could show up in training data or in front of human evaluators as a result. Nevertheless, it feels private, like no one in my life would see the things I write.&lt;/p&gt;
&lt;p&gt;I think there&amp;rsquo;s a third trait that aids in creating this kind of trust that&amp;rsquo;s harder to pin down. Something about the inhuman form factor &amp;ndash; something about how it feels like talking to a machine &amp;ndash; enables the comfort level and vulnerability I&amp;rsquo;ve expressed feeling above.&lt;/p&gt;
&lt;h3 id=&#34;learning-about-chloropropane-an-illustration-of-trust-and-distrust&#34;&gt;Learning about Chloropropane: An Illustration of Trust and Distrust&lt;/h3&gt;
&lt;p&gt;I asked the AI to give me an example of an organic chemistry homework problem. It asked me a question about chloropropane.&lt;/p&gt;
&lt;p&gt;I asked what chloropropane is used for. It told me it&amp;rsquo;s used as a pesticide.&lt;/p&gt;
&lt;p&gt;I asked if it&amp;rsquo;s used as a pesticide. It told me no.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve reproduced our conversation(s) below. The timestamps indicate separate &amp;ldquo;sessions&amp;rdquo;, meaning that each timestamped conversation is independent of the others. The AI had no way of looking at what was said in an earlier session. As you expand the sections, see the self-contradictions &lt;mark&gt;highlighted in yellow&lt;/mark&gt;.&lt;/p&gt;
&lt;style&gt;
details {
  margin-left: 2em;
}

summary {
  margin-left: -2em;
}
&lt;/style&gt;
&lt;p&gt;&lt;button id=&#34;expand-button&#34; onclick=&#34;expandCollapseAll()&#34;&gt;Expand All&lt;/button&gt;&lt;/p&gt;
&lt;script&gt;
  var expandButton = document.getElementById(&#39;expand-button&#39;);
  var isExpanded = false;

  function expandCollapseAll() {
    var detailsElements = document.getElementsByTagName(&#39;details&#39;);
    for (var i = 0; i &lt; detailsElements.length; i++) {
      detailsElements[i].open = !isExpanded;
    }
    isExpanded = !isExpanded;
    expandButton.textContent = isExpanded ? &#39;Close All&#39; : &#39;Expand All&#39;;
  }
&lt;/script&gt;
&lt;details&gt;
  &lt;summary&gt;00:47 AM&lt;/summary&gt;
  &lt;details&gt;
    &lt;summary&gt;Give me a organic chemistry homework problem&lt;/summary&gt;
      Calculate the enthalpy of combustion for 1-chloropropane in kJ/mol.
  &lt;/details&gt;
  &lt;details&gt;
    &lt;summary&gt;What does that mean?&lt;/summary&gt;
      Enthalpy of combustion is the amount of energy released when a compound is completely burned in oxygen. In this case, you will be calculating the amount of energy released when 1-chloropropane is completely burned in oxygen, expressed in units of kilojoules per mole (kJ/mol).
  &lt;/details&gt;
  &lt;details&gt;
    &lt;summary&gt;What is chloropropane used for?&lt;/summary&gt;
      Chloropropane is used as a precursor to other chemicals in the production of materials such as plasticizers, solvents, and lubricants. It is also &lt;mark&gt;used as a pesticide&lt;/mark&gt; in agriculture.
  &lt;/details&gt;
&lt;/details&gt;
&lt;details&gt;
  &lt;summary&gt;00:48 AM&lt;/summary&gt;
  &lt;details&gt;
    &lt;summary&gt;Is chloropropane a pesticide?&lt;/summary&gt;
      No, chloropropane is &lt;mark&gt;not a pesticide&lt;/mark&gt;. It is a colorless gas with a strong odor, used mainly in the production of other chemicals and in the &lt;mark&gt;manufacture of rubber&lt;/mark&gt; and plastics.
  &lt;/details&gt;
&lt;/details&gt;
&lt;details&gt;
  &lt;summary&gt;00:49 AM&lt;/summary&gt;
  &lt;details&gt;
    &lt;summary&gt;Is chloropropane used for making rubber?&lt;/summary&gt;
      No, chloropropane is &lt;mark&gt;not used for making rubber&lt;/mark&gt;.
  &lt;/details&gt;
  &lt;details&gt;
    &lt;summary&gt;What is it for?&lt;/summary&gt;
      Chloropropane is an industrial chemical used in the production of other chemicals including agrochemicals, pharmaceuticals, and &lt;mark&gt;dyes&lt;/mark&gt;.
  &lt;/details&gt;
&lt;/details&gt;
&lt;details&gt;
  &lt;summary&gt;00:50 AM&lt;/summary&gt;
    &lt;details&gt;
    &lt;summary&gt;Is chloropropane used in the production of dyes?&lt;/summary&gt;
      No, chloropropane is &lt;mark&gt;not used in the production of dyes&lt;/mark&gt;.
    &lt;/details&gt;
    &lt;details&gt;
    &lt;summary&gt;What is it used for?&lt;/summary&gt;
      Chloropropane is a chemical compound used as a solvent and intermediate in the production of a variety of products, including pharmaceuticals, pesticides, and other chemicals.
      Chloropropane is &lt;mark&gt;used as a solvent&lt;/mark&gt; in organic synthesis and in the production of pharmaceuticals, agrochemicals, and other chemicals.
    &lt;/details&gt;
    &lt;details&gt;
    &lt;summary&gt;Is chloropropane used in the production of pesticides?&lt;/summary&gt;
      No, chloropropane is &lt;mark&gt;not used in the production of pesticides&lt;/mark&gt;.
    &lt;/details&gt;
    What is it used for?
  &lt;/details&gt;
&lt;details&gt;
  &lt;summary&gt;00:51 AM&lt;/summary&gt;
  &lt;details&gt;
    &lt;summary&gt;Is chloropropane a solvent?&lt;/summary&gt;
      No, chloropropane is &lt;mark&gt;not a solvent&lt;/mark&gt;.
  &lt;/details&gt;
  &lt;details&gt;
    &lt;summary&gt;What is it used for?&lt;/summary&gt;
      Chloropropane is used as an intermediate in the production of solvents, pesticides, pharmaceuticals and other chemicals. It is also used as a refrigerant and as a propellant in aerosols.
  &lt;/details&gt;
&lt;/details&gt;
&lt;p&gt;You can see the AI blatantly contradicts itself repeatedly, and confidently so.&lt;/p&gt;
&lt;p&gt;While this conversation illustrates how I cannot trust the AI to be factual,
it also demonstrates the kind of trust that I do have for the AI.
It blatantly contradicted itself, yet I felt comfortable probing the depths of its knowledge,
asking questions in a volume that I would not have been comfortable asking of a human.&lt;/p&gt;
&lt;h3 id=&#34;strategies-for-mitigating-the-ais-fibs&#34;&gt;Strategies for mitigating the AI&amp;rsquo;s fibs&lt;/h3&gt;
&lt;p&gt;I didn&amp;rsquo;t get the AI to stop making things up. And I didn&amp;rsquo;t get it to admit uncertainty when it doesn&amp;rsquo;t know things.
But a few mitigation strategies did arise for dealing with the AI&amp;rsquo;s fibbing tendency.&lt;/p&gt;
&lt;p&gt;One was to probe the AI about topics I already know about in order to understand its limitations.
I had it teach me about math and algorithms concepts I was already quite familiar with.
My thinking here was that this would help me develop my intuition for what it&amp;rsquo;s like when it&amp;rsquo;s fibbing,
so I could better deal with
the inaccuracies on topics I&amp;rsquo;m less familiar with.&lt;/p&gt;
&lt;p&gt;A second mitigation that quickly became essential was having detailed records of what the AI said.
While I was drifting off to sleep, the AI might tell me something wrong and then contradict itself a minute later.
Without the record to verify this, the confidence of the contradiction would have a gas-lighting effect on me.
I might question myself &amp;ndash; did I remember the AI correctly?
Being able to see the contradiction highlighted, as above, helped keep me sane in the face of the AI&amp;rsquo;s unearned and contradictory confidence.&lt;/p&gt;
&lt;p&gt;Having the permanent record also allows me to look up the truth the next day, to find out how much of what I learned had basis in reality.&lt;/p&gt;
&lt;h3 id=&#34;other-benefits-of-having-the-ai-with-me&#34;&gt;Other benefits of having the AI with me&lt;/h3&gt;
&lt;p&gt;Central to Go Note Go&amp;rsquo;s design is that it has no screen. This is a purposeful choice, and enables so much of what I love about Go Note Go. However, sometimes I miss being able to see what I&amp;rsquo;ve written. This is where the assistant comes in.&lt;/p&gt;
&lt;p&gt;First though I must emphasize that on the whole, I actually really like that the lack of screen prevents me from wasting time rereading what I&amp;rsquo;ve written. But when I lose my train of thought entirely, it would be nice to remember what I wrote last.
For this, I can ask the assistant to read back what I wrote last, or even to summarize it concisely. If my mind has wandered and I want to continue typing where I left off, this feature is quite welcome!&lt;/p&gt;
&lt;p&gt;In this way, the AI compensates for the lack of screen.
It&amp;rsquo;s behaving somewhat like an intelligent screen reader.
With typical screen readers, navigation is performed spatially, and the reader speaks text at the indicated location. With the AI assistant, &amp;ldquo;navigation&amp;rdquo; is performed via a textual query, and the response can either be verbatim or an intelligent response like a summary or answer. I suspect AI assistants will quickly change the way accessibility technology operates, if they haven&amp;rsquo;t already done so.&lt;/p&gt;
&lt;h3 id=&#34;what-dont-you-send-to-the-ai&#34;&gt;What don&amp;rsquo;t you send to the AI?&lt;/h3&gt;
&lt;p&gt;As I drift off to sleep, I enter thoughts about a wide range of subjects that I don&amp;rsquo;t send to the AI assistant too. A quick scan of my recent Go Note Go writing (just from the last couple days, all since adding the assistant) shows the following topics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Plans for my upcoming California trip&lt;/li&gt;
&lt;li&gt;Observations about Go Note Go &amp;ndash; both improvements I&amp;rsquo;m looking forward to making and emergent behaviors I&amp;rsquo;m excited to share in future writing&lt;/li&gt;
&lt;li&gt;Thoughts about the future of AI&lt;/li&gt;
&lt;li&gt;Machine learning experiments I&amp;rsquo;m excited to run&lt;/li&gt;
&lt;li&gt;Thoughts I&amp;rsquo;d like to publish about, such as the unexpected dangers of reducing friction, or the less-appreciated benefits of repetition&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://twitter.com/Bieber&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Tweet ideas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Items I intend to buy&lt;/li&gt;
&lt;li&gt;Questions I want to ask either specific people, or the internet at large&lt;/li&gt;
&lt;li&gt;Lists of todos for the next day&lt;/li&gt;
&lt;li&gt;Reflections on the day&lt;/li&gt;
&lt;li&gt;Ideas to try, e.g. for technical problems I ran into that day&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The AI assistant merely augments my existing Go Note Go usage,
but hasn&amp;rsquo;t replaced it. 
&lt;a href=&#34;https://davidbieber.com/snippets/2023-01-16-go-note-go-features/&#34;&gt;All of Go Note Go&amp;rsquo;s other features&lt;/a&gt; &amp;ndash; particularly its always-on ability to quickly capture thoughts anywhere &amp;ndash; remain the driving reason I use Go Note Go so much.&lt;/p&gt;
&lt;h3 id=&#34;what-worked-well&#34;&gt;What worked well?&lt;/h3&gt;
&lt;p&gt;The best part of this process was being able to learn what I want to learn when I want to learn it.
While a deep probe into a topic inevitably turned up falsehoods, overall asking questions about things I was curious about worked really well.&lt;/p&gt;
&lt;p&gt;And I think about things differently at night. My brain processes topics that it hasn&amp;rsquo;t had a chance to think on throughout the day. It comes up with things it wants to do that it doesn&amp;rsquo;t come up with when it&amp;rsquo;s otherwise occupied throughout the day.&lt;/p&gt;
&lt;p&gt;I think of things I want to write, and the assistant helps me think through them and outline them.&lt;/p&gt;
&lt;p&gt;I think of people I want to reach out to. With Go Note Go, I can write them a message and approve it to send in the morning. (The assistant doesn&amp;rsquo;t really play a role here, but I thought I&amp;rsquo;d mention it anyway.)&lt;/p&gt;
&lt;p&gt;I think of things I want to know, and the assistant helps answer my questions.&lt;/p&gt;
&lt;p&gt;I think of ideas I want to try. Some of them I can try with the assistant, and others I just jot down to return to later.&lt;/p&gt;
&lt;p&gt;In many of these instances, the value of the AI assistant is that I can offload some of my thinking to it. It isn&amp;rsquo;t necessarily producing insights that I wouldn&amp;rsquo;t have come up with on my own, but it&amp;rsquo;s allowing me a moment&amp;rsquo;s rest while it does the thinking on my behalf. Then I can start from its thoughts as a baseline and build from there, higher than I could build on my own. On many other occasions, it genuinely surprises me with its good ideas.&lt;/p&gt;
&lt;p&gt;On a couple of nights, the AI took me exploring imaginary worlds. Similar to a text adventure game, it described my environment to me, and I gave it instructions like talking to a person, or exploring a building. With my eyes closed and my brain on the edge of sleep, it felt like dreaming while I was still awake and I quite enjoyed it.&lt;/p&gt;
&lt;h3 id=&#34;things-that-didnt-work-so-well&#34;&gt;Things that didn&amp;rsquo;t work so well&lt;/h3&gt;
&lt;p&gt;The main drawback of this system is the lack of trust in the accuracy of the AI&amp;rsquo;s statements, particularly when I&amp;rsquo;m trying to learn.
Other limitations were subtler and less dampening for the experience.&lt;/p&gt;
&lt;p&gt;When I tried to get it to teach me math, my 
&lt;a href=&#34;https://espeak.sourceforge.net/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;text to speech system (espeak)&lt;/a&gt; did quite poorly on reading the math aloud.
I would love to replace the text to speech system with one with better prosody and better math support.
Ideally, the text to speech system would speak with 
&lt;a href=&#34;https://www.youtube.com/watch?v=Qe6o9j4IjTo&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Grant Sanderson&amp;rsquo;s voice and cadence&lt;/a&gt;, and handle math notation seamlessly.
While this seems a cosmetic change, it does impact the set of topics I can discuss cleanly with the AI as I drift off.&lt;/p&gt;
&lt;p&gt;The dependence on an internet connection was another small drawback. I take my Go Note Go into the woods, used it during an Uber ride the airport today, and regularly use it when I fly. The AI assistant doesn&amp;rsquo;t work in these situations (the rest of Go Note Go continues to work fine) since it depends on having internet access. For a capability that is simple enough to not require AI, like reading back the topics I&amp;rsquo;ve written about recently, it feels quite silly to lose the capability when the internet is gone.&lt;/p&gt;
&lt;p&gt;Related to the internet dependence, the lack of privacy from OpenAI is another important drawback to me. The thoughts I produce as I drift off to sleep are deeply personal! I would much prefer not to send them off to OpenAI (the current version of the assistant is implemented with text-davinci-003).&lt;/p&gt;
&lt;p&gt;Finally, there&amp;rsquo;s another significant drawback, one you might have already picked up on: talking with an AI can get in the way of falling asleep.
I view talking with an AI while drifting off to sleep similarly to listening to reading a book, listening to an audiobook, or to a podcast before bed.
These activities require some amount of thought, but can also help to wind down and fall asleep.
Talking to the AI required no monitor, and hence to blue lights that can make falling asleep harder.
It simply requires some amount of restraint to stop the conversation and transition to sleep, just as one must put down a book and close their eyes if reading before bed.&lt;/p&gt;
&lt;p&gt;You can see in the chloropropane conversation reproduced above from the timestamps that I was talking to the AI at nearly 1am. I like to go to sleep 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-04-20-sleep-no-snippet/&#34;&gt;closer to 10:10pm&lt;/a&gt;, so clearly this drawback is real for me.&lt;/p&gt;
&lt;h3 id=&#34;it-left-me-wanting-more&#34;&gt;It left me wanting more&lt;/h3&gt;
&lt;p&gt;Having an assistant as I drifted off to sleep was great overall, even in spite of these drawbacks.
I was definitely left with a sense of wanting more though.&lt;/p&gt;
&lt;p&gt;I want more assistance from my assistant.
I want to be able to query my complete history of notes, asking questions like &amp;ldquo;What are some ideas I keep returning to?&amp;rdquo; or &amp;ldquo;Bring up all my outstanding Go Note Go TODOs.&amp;rdquo;
Perhaps I&amp;rsquo;ll be able to implement this with 
&lt;a href=&#34;https://gpt-index.readthedocs.io/en/latest/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;GPT-Index&lt;/a&gt;, or a 
&lt;a href=&#34;https://arxiv.org/abs/2203.08913&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Memorizing Transformer&lt;/a&gt;, but for now I do without.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d also love for my assistant to be able to take actions on my behalf. Maybe I can integrate 
&lt;a href=&#34;https://www.adept.ai/act&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Adept AI&amp;rsquo;s action transformer&lt;/a&gt; into my next iteration to achieve this. For example, I want to be able tell the assistant my shopping list, and have it populate my Amazon cart. Then, when I&amp;rsquo;m back at a computer, I can review the cart and click submit, saving myself time shopping.&lt;/p&gt;
&lt;p&gt;Sometimes (albeit rarely :P) I&amp;rsquo;m not at a Go Note Go, but I still want to talk to my AI assistant.
For that, I&amp;rsquo;ve used Twilio so I can call my assistant on the phone.
I use this when I&amp;rsquo;m driving or walking around. But that is a subject for another post entirely.&lt;/p&gt;
&lt;h3 id=&#34;concluding-remarks&#34;&gt;Concluding remarks&lt;/h3&gt;
&lt;p&gt;Adding an AI assistant to Go Note Go has been an absolute joy and I continue to use it almost every night.
Despite its tendency to make things up &amp;ndash; or more charitably, to hallucinate &amp;ndash; it has still earned my trust in a more visceral way.
I&amp;rsquo;m curious to see what use cases persist after I&amp;rsquo;ve had this capability for a longer period of time.&lt;/p&gt;
&lt;p&gt;Of course, the AI assistant is not the only reason that Go Note Go is such a critical component in my life.
Go Note Go can do so much more &amp;ndash; 
&lt;a href=&#34;https://davidbieber.com/snippets/2023-01-16-go-note-go-features/&#34;&gt;a complete and concise overview of its capabilities is here&lt;/a&gt; &amp;ndash;
like letting me 
&lt;a href=&#34;https://davidbieber.com/post/2022-01-08-new-messager-setup/&#34;&gt;send messages as I drift off to sleep&lt;/a&gt; and helping me 
&lt;a href=&#34;https://davidbieber.com/post/2022-02-07-keyboards-everywhere/&#34;&gt;reclaim my attention in a world full of distractions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With the AI assistant added in, however, I feel like I have a new superpower. I can offload computation from my brain to it, and explore worlds of thought I could never have entered on my own.&lt;/p&gt;
&lt;p&gt;Go Note Go is also 
&lt;a href=&#34;https://github.com/dbieber/GoNoteGo&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;completely open source&lt;/a&gt;. I encourage the hacker-tinkerers among you to join me in the world of headless computing and try it for yourself.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Anything I type on this keyboard gets automatically uploaded to my notes as soon as the keyboard is in range of wifi. This allows for offline usage, e.g. while driving or camping. These were the two use-cases that inspired me to build the device. Now my main use-case is capturing ideas while drifting off to sleep.
It also has a microphone, so if speaking feels like it would take less energy than talking, I can speak my notes instead. This feature is what enables the driving use case, as of course I don&amp;rsquo;t type while I drive! &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;If I prefer speaking, I can also trigger these commands with the hot word &amp;ldquo;go go&amp;rdquo;, e.g. saying &amp;ldquo;go go time&amp;rdquo; gets the time. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Explicit Ontologies in a World Without</title>
      <link>https://davidbieber.com/snippets/2022-12-16-note-taking-ontologies/</link>
      <pubDate>Fri, 16 Dec 2022 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-12-16-note-taking-ontologies/</guid>
      
      <description>&lt;h2 id=&#34;background-ontologies-in-note-taking&#34;&gt;Background: Ontologies in Note-taking&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ll do my best to get the context for this thought down quickly, but I don&amp;rsquo;t think I&amp;rsquo;ll do a good job. Feel free to ask me if you&amp;rsquo;d like to understand the context better.&lt;/p&gt;
&lt;p&gt;In a note-taking system like C. or Tana, objects exist in an ontology&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;. This means that an object can have a type. That type definition can have properties. For example my notes might be full of people. Each person might have a birthday and contact info and a height and a handedness.&lt;/p&gt;
&lt;p&gt;Having ontologies be explicit can provide a lot of value in a note-taking system.
In particular: (1) This can enable powerful auto-complete / templating features. (2) This can enable powerful search functionality. (3) This can enable integrations with other specialized features (like a calendar, a contacts view, a shopping experience&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;, whatever) or external software.&lt;/p&gt;
&lt;h2 id=&#34;agenda-three-key-points&#34;&gt;Agenda: Three Key Points&lt;/h2&gt;
&lt;p&gt;Next I want to make a series of points that interact a bit:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ontologies take time to maintain, and are difficult to design well.&lt;/li&gt;
&lt;li&gt;Large language models may be able to provide all three value propositions without actually needing the explicit ontology.&lt;/li&gt;
&lt;li&gt;Even if the above two points are right, there&amp;rsquo;s still value to explicit ontologies in a world where we don&amp;rsquo;t spend much time being explicit about our ontologies.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&amp;rsquo;s this third and final point, which I realize I haven&amp;rsquo;t made clear just yet, that is the main thought I wanted to share in this snippet. Before we get there though, let&amp;rsquo;s expand on the first two points.&lt;/p&gt;
&lt;h2 id=&#34;doing-ontologies-manually-is-hard&#34;&gt;Doing Ontologies Manually is Hard&lt;/h2&gt;
&lt;p&gt;Coming up with useful ontologies is hard. Take the Person example from above.
Is it important that every person has an Interests field? Almost certainly not; you might not care to write down the interests of your dentist, for example. If you don&amp;rsquo;t like that example, consider an Education field. You probably don&amp;rsquo;t care to write down the educational history of everyone that shows up in your notes.&lt;/p&gt;
&lt;p&gt;But if you&amp;rsquo;re building a gift recommender, then an interests field might be critical. And if you&amp;rsquo;re building a job recommender, an education field might be critical.&lt;/p&gt;
&lt;p&gt;A risk you might run having an ontology in your notes is that it might discourage you from putting something in your notes because it doesn&amp;rsquo;t fit the ontology.
Suppose you avoid this risk, though, and manage to freely add information to your notes undeterred by the ontology&amp;rsquo;s constraints.
A second possible risk you run is that your ontology winds up being extremely sparse.
You add fields as you need them, but lots of fields only apply to a single instance, rather than to the majority of instances of a type. Is your ontology still useful at that point?&lt;/p&gt;
&lt;p&gt;A third potential risk, which extends the second, is that as your ontology grows&amp;hellip; you might end up with a type having two very similar fields. E.g. Person could end up with both a &amp;ldquo;Likes&amp;rdquo; field &lt;em&gt;and&lt;/em&gt; an &amp;ldquo;Interests&amp;rdquo; field. Why might this happen? Two reasons come to mind: One is that you simply have a bunch of fields, and so you accidentally use a new name (&amp;ldquo;Likes&amp;rdquo;) when referring to an existing attribute (&amp;ldquo;Interests&amp;rdquo;). The second is that &amp;ldquo;Likes&amp;rdquo; and &amp;ldquo;Interests&amp;rdquo; might mean slightly different things to you. That&amp;rsquo;s fine, if you want to track them separately. But these are highly correlated! And now you&amp;rsquo;re left with a dilemma (&amp;ldquo;Risk 4&amp;rdquo;, let&amp;rsquo;s call it): do you put the information in both the &amp;ldquo;Likes&amp;rdquo; and the &amp;ldquo;Interests&amp;rdquo; field? That would increase the maintenance burden of your note-base substantially (if you care about completeness/having the info you enter be maximally useful, which you might, in order to get the benefits of ontologies listed above). Or do you only put the information in one of the two fields? If you do that, then you risk your use of the ontology failing when you search for &amp;ldquo;Person with Interest in Table Tennis&amp;rdquo; only to find that half your table-tennis friends &amp;ldquo;Like&amp;rdquo; Table Tennis while the other half have an &amp;ldquo;Interest&amp;rdquo; in it.&lt;/p&gt;
&lt;p&gt;Finally, building ontologies takes time. Let&amp;rsquo;s turn our attention&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; to large language models, because you might not need to spend your time on ontologies in the near future.&lt;/p&gt;
&lt;h2 id=&#34;llms-reduce-the-need-for-explicit-ontologies&#34;&gt;LLMs reduce the need for explicit ontologies&lt;/h2&gt;
&lt;p&gt;Large language models&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt; may be able to provide many of the benefits of ontologies without the need for explicit ontologies. These models can understand and extract relevant concepts and relationships from unstructured text, allowing one to search and retrieve information without the need to pre-define an ontology.&lt;/p&gt;
&lt;p&gt;Recall the three benefits of ontologies that we&amp;rsquo;re interested in: auto-complete/templates, search, and integration with specialized systems.&lt;/p&gt;
&lt;h4 id=&#34;search&#34;&gt;Search&lt;/h4&gt;
&lt;p&gt;It&amp;rsquo;s easiest to imagine how large language models are going to be useful for search first.
Imagine that instead of having ontologies in your note-base, you simply have free-form text.
You still might say that David is interested in table tennis, but there would be no formal &amp;ldquo;Interests&amp;rdquo; attribute linking David and Table Tennis.
If a large language model understands that text, then it will still be able to handle queries like &amp;ldquo;what is David interested in?&amp;rdquo; and &amp;ldquo;contacts who like table tennis?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;You can even try this on a small scale today in 
&lt;a href=&#34;https://chat.openai.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;ChatGPT&lt;/a&gt;. Paste the following text into ChatGPT and it answers the questions correctly. I wont argue the case here, but I fully expect this to work on the scale of a full note-base in the coming months-years.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;Mary likes hockey, collects coins, and reads sci-fi.
Glenn plays table tennis, collects rocks, and reads fantasy.
My dentist recommends the book &amp;quot;Jaws&amp;quot;. Next apt is March 6.
Peter plays scrabble and enjoys table tennis. Hanging out next Tuesday (Dec 20)

Who likes table tennis?
What are my dentist&#39;s interests?
Does my dentist like table tennis?
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;integration-with-specialized-systems&#34;&gt;Integration with Specialized Systems&lt;/h4&gt;
&lt;p&gt;One of the key reasons ontologies are useful is they allow for specialized systems to access the information stored in the ontology/notes, in order to provide a quality domain-specific experience using the data from the notes.&lt;/p&gt;
&lt;p&gt;This could take the form of a specialized contacts view of the contacts data found in your notes. It could be a specialized calendar view of time-annotated data in your notes. It could be the shopping experience I described in a footnote, which uses your contacts&#39; interests to surface gift suggestions. The possibilities are numerous.&lt;/p&gt;
&lt;p&gt;If search is robust (and it&amp;rsquo;s not totally clear that LLM search is going to be robust enough, but I suspect that it will be), then the data access requirements for these specialized integrations could be satisfied by the search described in the preceding section.&lt;/p&gt;
&lt;p&gt;Two ways to think about this:
(1) The specialized system issues queries &amp;ndash; possibly even natural language queries &amp;ndash; about the notebase. It gets structured results back. It uses the structured results to render the specialized domain-specific experience.
(2) The raw text in &lt;mark&gt;the note-base is being projected onto a temporary domain-specific ontology just for the specialized system&lt;/mark&gt;. E.g. the shopping experience might require an ontology where each Person has interests, while a separate job matching system might require an ontology where each Person has an educational background. Using the magic of LLMs, the raw text data is projected into the structured ontology needed by each system. But there&amp;rsquo;s no &amp;ldquo;one&amp;rdquo; ontology living in the note-base that the note-taker needs to maintain.&lt;/p&gt;
&lt;p&gt;Maybe these two ways are actually the same. 🤷&lt;/p&gt;
&lt;p&gt;At this point we&amp;rsquo;ve seen the first place where ontologies are useful even in this raw-text focused LLM-centric world. I&amp;rsquo;ve &lt;mark&gt;highlighted&lt;/mark&gt; it. We&amp;rsquo;ll come back to it shortly.&lt;/p&gt;
&lt;h4 id=&#34;auto-complete--templating&#34;&gt;Auto-complete / Templating&lt;/h4&gt;
&lt;p&gt;We come now to one of the main value-adds of an ontology: having a nice template to fill in about an object. Do we lose this in a raw-text LLM-centric world? By default, yes. But we can (very likely) use LLM-ish tech to implement an auto-complete / templating feature, arguably one that&amp;rsquo;s (in some ways) better than we get in an ontology-centric world.&lt;/p&gt;
&lt;p&gt;How? We can &lt;mark&gt;use the LLM-ish to suggest fields for an entity when we create it&lt;/mark&gt;. For example, when we mention a person, we can have our system insert fields (with blanks to be filled in) for the attributes that seem relevant to the person in the given context.
If we&amp;rsquo;re writing about how we met someone at a dinner party, it might provide an Interests field. Whereas if we&amp;rsquo;re writing about people we met at a career fair, it might provide an Education field.&lt;/p&gt;
&lt;p&gt;In this setting, the fields aren&amp;rsquo;t there to enable datalog search queries or populate a database; rather, the fields are there for human purposes: to prompt us to write the things we would want to write, and relieve us a bit of typing and a bit of cognitive load.
The search and integrations are going to work just fine whether the field is called &amp;ldquo;Interests&amp;rdquo; or &amp;ldquo;Likes&amp;rdquo; because the LLM understands that these are (in most contexts) synonyms.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve now introduced the second place where ontologies are useful even in a raw-text focused LLM-centric world, again &lt;mark&gt;highlighted&lt;/mark&gt;.&lt;/p&gt;
&lt;p&gt;In what ways is this proposed hypothetical templating feature better than an ontology-based templating feature? Recall the risks we discussed earlier: ontology maintenance runs the risk of there being lots of little-used fields in an ontology. In a naive ontology-based templating system, all these extra fields would clutter the interface, whereas in our proposed hypothetical templating feature, only a relevant subset of the fields show up by default.&lt;/p&gt;
&lt;p&gt;In what ways is this proposed hypothetical templating feature worse? Well, it loses the explicit association between objects of the same type. If later you decide you want all people to have a &amp;ldquo;Formal Name&amp;rdquo; attribute, there&amp;rsquo;s no clear source-of-truth place to add this attribute to all people. You could query for a list of all people, and then add to your notes &amp;ldquo;X&amp;rsquo;s formal name is Y&amp;rdquo; for each of the people. Just brainstorming; maybe this isn&amp;rsquo;t a drawback after all; I&amp;rsquo;ll have to keep thinking on this one.&lt;/p&gt;
&lt;h2 id=&#34;explicit-ontologies-in-a-world-without&#34;&gt;Explicit Ontologies in a World Without&lt;/h2&gt;
&lt;p&gt;Looking back over the &lt;mark&gt;highlighted&lt;/mark&gt; text, we can see that there are at least two places where explicit ontologies remain useful even in a raw-text focused LLM-centric world (that is, in a note-base full of raw text, not backed by an explicit ontology).&lt;/p&gt;
&lt;p&gt;The first was during querying for domain-specific experiences. There we saw the value of having the raw text in the note-base projected onto a temporary domain-specific ontology just for a specialized system.&lt;/p&gt;
&lt;p&gt;The second was for templating/auto-complete, one of the main values of an ontology. Using LLMs we can provide the appearance of there being an ontology without the note-base actually being backed by an explicit ontology.&lt;/p&gt;
&lt;p&gt;All of this relies on some amount of speculation about where our LLM&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt; technology is going and what its coming capabilities will be. I&amp;rsquo;m happy to stand by this speculation, and happy to discuss.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Bear in mind I&amp;rsquo;ve used neither of these systems! Take my thoughts with grains of salt. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I just chose a random example. But anyway, the idea is that you might build a shopping widget that uses the data about your contacts&#39; preferences to surface gift ideas for them while you&amp;rsquo;re shopping. The ontology way to do this is for each Person in your notes to have a Likes or Interests field, which the shopping experience can access. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I was planning on squeezing a reference to &amp;ldquo;Factory factories&amp;rdquo; into this section, but then it didn&amp;rsquo;t fit in, so just sticking this in a footnote. &lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I&amp;rsquo;m using the term large language model here in a loose sense. I basically mean tech largely dependent on deep learning, including advances expected to come in the next few years. It&amp;rsquo;s easier to just say LLM though, even though that oversimplifies. &lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Castles in the Clouds: Why we believe what we believe</title>
      <link>https://davidbieber.com/snippets/2022-12-13-castles-in-the-clouds/</link>
      <pubDate>Tue, 13 Dec 2022 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-12-13-castles-in-the-clouds/</guid>
      
      <description>&lt;p&gt;We all live in castles in the clouds.&lt;/p&gt;
&lt;h3 id=&#34;building-our-castles&#34;&gt;Building our Castles&lt;/h3&gt;
&lt;p&gt;When we are young, we gather bricks. Each of our experiences is a brick. Each thing we learn is a brick, allowing us to build higher.
Whenever we learn something new, it is supported by things we already know.
The new blocks are laid to rest atop the old ones.&lt;/p&gt;
&lt;p&gt;Over our long lives, we construct beautiful tall towers using thousands of bricks, representing everything we know. These towers take us to great heights.
We find ourselves in a castle in the clouds.&lt;/p&gt;
&lt;p&gt;When we look down, we can&amp;rsquo;t always see clearly what&amp;rsquo;s supporting us. We might imagine we&amp;rsquo;re being supported differently than we really are. We might find, like coyote in the Road Runner cartoons, that we&amp;rsquo;re not being supported any more at all.&lt;/p&gt;
&lt;h3 id=&#34;tumbling-towers&#34;&gt;Tumbling Towers&lt;/h3&gt;
&lt;p&gt;This metaphor lends itself to a few consequences. What happens if you find out that one of your beliefs is wrong?&lt;/p&gt;
&lt;p&gt;If one of our beliefs at the top of the tower is wrong, we can easily replace it with a new belief.
We can swap out one brick for another.
However, if a brick at the base of the tower is removed, our whole tower can come crumbling down.
This is what happens when people question basic assumptions, perhaps like a formerly devout individual questioning their belief in God.&lt;/p&gt;
&lt;h3 id=&#34;forgetting-castles-in-the-clouds&#34;&gt;Forgetting: Castles in the Clouds&lt;/h3&gt;
&lt;p&gt;However, learning that we were wrong is not the only way the foundations of our tower can come under pressure.
Over time, even the mightiest of castles is subject to wear and tear.
Our memories fade, our bricks erode. And as we age, we may find ourselves holding onto beliefs but not remembering exactly where they came from.
We know that we believe something strongly, and we know that there was a reason for believing it, but that reason is now lost to us.
Maybe it was something we learned in school as a child, and it made sense when we learned it, but we don&amp;rsquo;t remember the reasoning anymore.&lt;/p&gt;
&lt;p&gt;When this happens, our tower does not fall.
We retain our confidence in our beliefs at the top of the tower.
But the tower is now floating; it exists in the clouds, but it is not connected to the ground.
It isn&amp;rsquo;t grounded.&lt;/p&gt;
&lt;p&gt;We all live in castles in the clouds.
It would behoove us to look down every once in a while and see how high we&amp;rsquo;re floating, and to try to repair some of the bricks that have begun to erode away.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Thoughts on ChatGPT</title>
      <link>https://davidbieber.com/snippets/2022-12-08-thoughts-on-chatgpt/</link>
      <pubDate>Thu, 08 Dec 2022 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-12-08-thoughts-on-chatgpt/</guid>
      
      <description>&lt;p&gt;This blog post was entirely written by me, David Bieber, a human being. I did not consult with ChatGPT or Bieber Bot or any other assistants or conversational agents in the writing of this post. It is likely this will now be a rare occurrence, and that subsequent posts will generally be written with an assistant at my side.&lt;/p&gt;
&lt;h2 id=&#34;reminder-this-is-a-snippet&#34;&gt;Reminder: This is a snippet&lt;/h2&gt;
&lt;p&gt;If this were an ordinary blog post, I might set aside some space to bring you up to speed with what ChatGPT is (it&amp;rsquo;s a conversational assistant &amp;ndash; a chatbot &amp;ndash; but more sophisticated than SmarterChild ever dreamed she could be). But this is a snippet, a mini blog post written for no audience and with no quality bar to publication, so I will press on without doing so.&lt;/p&gt;
&lt;h2 id=&#34;reactions-to-chatgpt&#34;&gt;Reactions to ChatGPT&lt;/h2&gt;
&lt;p&gt;Futility. Existential dread. Unsettled. Excitement! There are lots of possible reasons one might be concerned about the release of ChatGPT by OpenAI. For me, the ones that hit me hardest were about my own ability to stay relevant a few years down the line. Bear in mind, when you hear this concern, that it&amp;rsquo;s not just about ChatGPT&amp;rsquo;s current capabilities. It&amp;rsquo;s about the expected advancements that are coming in the next several months or years.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not concerned about being &amp;ldquo;replaced&amp;rdquo; wholesale. I am concerned about my own ability to stay relevant and continue to provide (as significant) value professionally and personally a few year&amp;rsquo;s down the line, heightening competition and expectations, a future need to be always on / always adapting to a world changing faster each year. An economic future full of contradictions I haven&amp;rsquo;t been able to wrap my head around yet. And a large number of people who are going to have sudden shifts in their lives, jobs, etc.&lt;/p&gt;
&lt;p&gt;I previously thought self-driving trucks would be the one Big Shock, and everything else would get automated more gradually (in terms of people/year). I&amp;rsquo;m in the process of reconsidering.&lt;/p&gt;
&lt;h2 id=&#34;expected-advancements&#34;&gt;Expected Advancements&lt;/h2&gt;
&lt;p&gt;Future capabilities will include 
&lt;a href=&#34;https://openai.com/blog/webgpt/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;web browsing&lt;/a&gt;, 
&lt;a href=&#34;https://www.adept.ai/act&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;taking actions&lt;/a&gt; on your computer, and accessing your personal files (documents, emails, chats, etc) (with your permission, of course). We&amp;rsquo;re also going to see major improvements in quality from human feedback, and from a larger model trained on more data. I expect this is coming quite soon. A bit further down the line, integration of multiple modalities (e.g. image generation, audio, video) will come too.&lt;/p&gt;
&lt;h2 id=&#34;using-chatgpt-with-my-roam-research-notes&#34;&gt;Using ChatGPT with my Roam Research Notes&lt;/h2&gt;
&lt;p&gt;I use 
&lt;a href=&#34;https://davidbieber.com/projects/go-note-go&#34;&gt;Go Note Go&lt;/a&gt; to jot down miscellaneous thoughts. They are often scattered and always ill-formatted. ChatGPT is able to pull out a clean list of TODOs from my notes, unperturbed by the messy format they start in. Integrating conversational assistants into more of my personal documents is going to be immensely valuable. Excited to see what progress on retrieval augmented models brings next year.&lt;/p&gt;
&lt;h2 id=&#34;building-products-with-chatgpt&#34;&gt;Building Products with ChatGPT&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Voice assistant:&lt;/strong&gt; Tonight I prototyped a voice conversational assistant with Twilio using GPT-3.5 (davinci-text-003). I&amp;rsquo;m excited to try it out with ChatGPT as well. Being able to place a phone call to use the power of a conversational assistant is convenient, especially when driving. There, a phone call is easy but a text based app is not safe.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Medical robo-intake:&lt;/strong&gt; At the doctor&amp;rsquo;s office, you typical fill out an intake form which is impersonal. Then, if the doctor is busy, you may not get to tell them all the details that could be relevant to your case. Using a conversational assistant to perform the medical intake could be quite valuable. We wouldn&amp;rsquo;t be relying on the AI to have robust medical knowledge or make any diagnosis; it would simply ask relevant questions to try to elicit any details that might be pertinent for the doctor to know. The doctor could still see the full conversation, as well as a robo-summary with the highlights.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Personal tutor:&lt;/strong&gt; One drawback of the current ChatGPT system is it isn&amp;rsquo;t always factual, making it challenging to use for learning unfamiliar subject matter. I envision a system in which a human tutor can view their student&amp;rsquo;s conversations with an AI-tutor, and can jump in with corrections and suggestions when needed. Another important aspect of an AI personal tutor will be curriculum setting (involving push messages, not just reactive messages), and goal setting, but the most important aspect is just that you can go down whatever rabbit-hole tangents catch your eye while progressing through the guided lessons.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Teddy Bear Programmer:&lt;/strong&gt; ChatGPT already provides a great developer experience, where you can ask it technical questions or to perform code-writing tasks. To improve this experience, we can build a system where it always has visibility into the context of your development efforts. E.g. it can see your recent terminal usage or your current editor window. So when you ask it questions, it knows why you&amp;rsquo;re asking.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The &amp;ldquo;Clink&amp;rdquo; Feature for Go Note Go:&lt;/strong&gt; The idea here is that when you take notes on Go Note Go, and someone else also has taken notes, you should be able to &amp;ldquo;clink&amp;rdquo; your two note-bases in order to find points of commonality between you. Then you can hit it off and discuss your common interests! The ChatGPT tech makes implementing this easier.&lt;/p&gt;
&lt;h2 id=&#34;my-own-uses-of-chatgpt-so-far&#34;&gt;My Own Uses of ChatGPT so Far&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Writing a legal document&lt;/strong&gt; for a car sharing agreement for my partner.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Writing a blog post&lt;/strong&gt; on 
&lt;a href=&#34;https://davidbieber.com/snippets/2022-12-03-spicy-conversations/&#34;&gt;the salt, fat, acid, heat metaphor&lt;/a&gt;. Revising the post was done with the help of ChatGPT as well.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Learning&lt;/strong&gt; about variational autoencoders, about music theory, violin and guitar, and about Rust and building Chrome Extensions, and about topics in medicine, history, and science.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Programming&lt;/strong&gt; in languages I&amp;rsquo;m less familiar with and using APIs I&amp;rsquo;m unfamiliar with.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reading papers&lt;/strong&gt; and having ChatGPT summarize sections as I read them. Similarly, having ChatGPT summarize websites and blog posts as I browse the internet.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Extracting clean TODOs&lt;/strong&gt; from my messy Go Note Go notes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Generating descriptions&lt;/strong&gt; for Stable Diffusion, which in turn generates stunning imagery.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Brainstorming&lt;/strong&gt; uses of ChatGPT, questions to ask people, thoughts on education and psychology, topics in medicine, etc.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Just for fun&lt;/strong&gt; generating simple stories, bad jokes, poor stand up comedy routines, and silly parody songs.&lt;/p&gt;
&lt;h2 id=&#34;excitement-for-the-future&#34;&gt;Excitement for the future&lt;/h2&gt;
&lt;p&gt;Despite my visceral reactions of futility and existential dread noted above&amp;hellip; I&amp;rsquo;m excited and energized for the future. There&amp;rsquo;s no doubt this technology is going to provide a tremendous amount of value and it&amp;rsquo;s going to come quick.
Yes, the space of possible futures seems narrower today than it did before the ChatGPT launch.
Now we must aim for the best possible future among all those that remain open.
And ultimately, does not every passing moment narrow the space of possible futures?
The space of &lt;em&gt;proximal&lt;/em&gt; possible futures, on the other hand, has now been pried wide open.
Machine-learning driven conversational assistants present so many possibilities.
My brainstormings so far only scratch the surface.
I&amp;rsquo;m excited to get building, and to unearth more about what this tech is doing to our future.&lt;/p&gt;
&lt;p&gt;(Want to build together? Get in touch!)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Spicing Up Your Conversations: The Power of Salt, Acid, Fat, and Heat</title>
      <link>https://davidbieber.com/snippets/2022-12-03-spicy-conversations/</link>
      <pubDate>Sat, 03 Dec 2022 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-12-03-spicy-conversations/</guid>
      
      <description>&lt;p&gt;Good conversation is an essential part of human interaction. It allows us to connect with others, share our thoughts and ideas, and learn from one another. But in a world where we are constantly bombarded with 
&lt;a href=&#34;https://davidbieber.com/snippets/2022-07-20-keyboards-everywhere/&#34;&gt;information and distractions&lt;/a&gt;, it can be difficult to hold someone&amp;rsquo;s attention and have a truly engaging conversation.&lt;/p&gt;
&lt;p&gt;One way to improve the quality of our conversations is by using the elements of &amp;ldquo;salt, acid, fat, and heat&amp;rdquo;. This metaphor is based on the culinary philosophy of chef and food writer Samin Nosrat, who popularized the idea of these four elements as the foundation of good cooking in her book 
&lt;a href=&#34;https://www.saltfatacidheat.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&amp;ldquo;Salt, Acid, Fat, Heat: Mastering the Elements of Good Cooking&amp;rdquo;&lt;/a&gt;.  In this blog post, we will explore what each of these elements represents in the context of conversation, and how you can use them to improve the quality of your conversations. So grab a cup of coffee, get comfortable, and let&amp;rsquo;s dive into the world of &amp;ldquo;Salt, Acid, Fat, and Heat&amp;rdquo;!&lt;/p&gt;
&lt;h2 id=&#34;salt-humor-wit-and-charm&#34;&gt;Salt (Humor, wit, and charm)&lt;/h2&gt;
&lt;p&gt;The element of salt in conversation represents the humor, wit, and charm that can make a conversation engaging and enjoyable. Just as a pinch of salt can enhance the flavors of a dish, a bit of humor or wit can add flavor and interest to a conversation.&lt;/p&gt;
&lt;p&gt;Here are a few examples of how you can use the element of salt in your conversations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use humor to lighten the mood and make the conversation more enjoyable. A well-timed joke or funny observation can help to break the ice and put everyone at ease.&lt;/li&gt;
&lt;li&gt;Add a touch of wit to keep the conversation interesting. Clever wordplay or a clever turn of phrase can add sparkle to a conversation and keep things lively.&lt;/li&gt;
&lt;li&gt;Use charm to make the conversation more engaging. A warm smile, a friendly tone, or a flattering comment can help to make the conversation more enjoyable for everyone involved.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By incorporating the element of salt into your conversations, you can add flavor and interest, and make your interactions with others more enjoyable.&lt;/p&gt;
&lt;h2 id=&#34;acid-curiosity-and-skepticism&#34;&gt;Acid (Curiosity and skepticism)&lt;/h2&gt;
&lt;p&gt;The element of acid in conversation represents the curiosity, skepticism, and critical thinking that can keep a conversation lively and stimulating. Just as a dash of citrus juice or vinegar can add a tangy and lively flavor to a dish, a bit of curiosity or skepticism can add a lively and stimulating edge to a conversation.&lt;/p&gt;
&lt;p&gt;Here are a few examples of how you can use the element of acid in your conversations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use curiosity to keep the conversation moving. Asking open-ended questions and expressing a genuine interest in the other person&amp;rsquo;s thoughts and opinions can help to keep the conversation flowing and prevent it from becoming stagnant.&lt;/li&gt;
&lt;li&gt;Add a touch of skepticism to challenge assumptions and keep things interesting. Asking follow-up questions and challenging the other person&amp;rsquo;s assumptions can help to add depth and complexity to the conversation, and prevent it from becoming too one-sided.&lt;/li&gt;
&lt;li&gt;Use critical thinking to foster deeper discussions. Analyzing the other person&amp;rsquo;s arguments and offering counterpoints or alternative perspectives can help to stimulate more in-depth and meaningful discussions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By incorporating the element of acid into your conversations, you can add a lively and stimulating flavor, and keep your interactions with others engaging and interesting.&lt;/p&gt;
&lt;h2 id=&#34;fat-empathy-and-vulnerability&#34;&gt;Fat (Empathy and vulnerability)&lt;/h2&gt;
&lt;p&gt;The element of fat in conversation represents the empathy, vulnerability, and emotional intelligence that can make a conversation meaningful and heartfelt. Just as fat can add richness and depth to a dish, empathy, vulnerability, and emotional intelligence can add depth and meaning to a conversation.&lt;/p&gt;
&lt;p&gt;Here are a few examples of how you can use the element of fat in your conversations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use empathy to create a more understanding and compassionate atmosphere. Showing that you understand and can relate to the other person&amp;rsquo;s feelings can help to create a sense of connection and build trust.&lt;/li&gt;
&lt;li&gt;Express vulnerability to foster deeper connections. Sharing your own thoughts and feelings, and being open and honest about your experiences, can help to create a more intimate and authentic conversation.&lt;/li&gt;
&lt;li&gt;Use emotional intelligence to navigate difficult conversations. Being aware of your own emotions and those of the other person can help you to communicate more effectively and navigate challenging conversations in a sensitive and constructive way.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By incorporating the element of fat into your conversations, you can add richness and depth, and make your interactions with others more meaningful and heartfelt.&lt;/p&gt;
&lt;h2 id=&#34;heat-enthusiasm-and-excitement&#34;&gt;Heat (Enthusiasm and excitement)&lt;/h2&gt;
&lt;p&gt;The element of heat in conversation represents the passion, enthusiasm, and excitement that can make a conversation engaging and dynamic. Just as heat can add flavor and excitement to a dish, passion and enthusiasm can energize and enliven a conversation.&lt;/p&gt;
&lt;p&gt;Here are a few examples of how you can use the element of heat in your conversations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use passion to add energy and enthusiasm to the conversation. Sharing your excitement and enthusiasm about a topic can help to get the other person interested and engaged.&lt;/li&gt;
&lt;li&gt;Add enthusiasm to keep the conversation moving. Being energetic and upbeat can help to keep the conversation lively and prevent it from becoming dull or tedious.&lt;/li&gt;
&lt;li&gt;Use excitement to add a spark to the conversation. Sharing something interesting or surprising can add a bit of excitement to the conversation and keep things interesting.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By incorporating the element of heat into your conversations, you can add warmth and energy, and make your interactions with others more engaging and dynamic.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The elements of &amp;ldquo;salt, acid, fat, and heat&amp;rdquo; can be useful tools for crafting engaging and enjoyable conversations. By incorporating these elements into your discussions, you can add flavor, liveliness, depth, and warmth to your interactions with others.&lt;/p&gt;
&lt;p&gt;Using the element of salt can add humor, wit, and charm to your conversations, making them more enjoyable for all involved. The element of acid can provide a tangy and lively flavor, keeping the conversation stimulating and interesting. The element of fat can add empathy, vulnerability, and emotional intelligence, making your conversations more meaningful and heartfelt. And the element of heat can add passion, enthusiasm, and excitement, making your conversations engaging and dynamic.&lt;/p&gt;
&lt;p&gt;By mastering the use of these elements, you can improve the quality of your conversations and make your interactions with others more enjoyable and fulfilling. So the next time you have a conversation, think about how you can use salt, acid, fat, and heat to craft a delicious and well-balanced interaction.&lt;/p&gt;
&lt;p&gt;Finally, I must note that this snippet was created with the assistance of a 
&lt;a href=&#34;https://chat.openai.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;large language model&lt;/a&gt;, which helped to generate the majority of the text. The final version of the text was curated and edited by a human to ensure that it was clear and coherent. The idea of using &amp;ldquo;salt, acid, fat, and heat&amp;rdquo; as a metaphor for conversation came from a conversation with my partner Adriana, and the model did the rest. Did the model&amp;rsquo;s text provide sufficient salt, acid, fat, and heat to keep you interested and engaged?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Ugh Task Night</title>
      <link>https://davidbieber.com/snippets/2022-10-24-ugh-task-night/</link>
      <pubDate>Mon, 24 Oct 2022 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-10-24-ugh-task-night/</guid>
      
      <description>&lt;p&gt;Boo! 👻 Ugh Task Night is coming!&lt;/p&gt;
&lt;p&gt;This is the second year I&amp;rsquo;m hosting Ugh Task Night, the scariest night of the year. Ugh Task Night takes place in late October, right around that other spooky holiday.
At Ugh Task Night, friends come together for an evening to do the scariest thing of all, their Ugh Tasks. We gather (virtually, on GatherTown) and, interspersed with chatting, do the things we dread most of all, generally to a feeling of significant relief. By doing our Ugh Tasks with friends, in a setting of care and support, we can face our inner beasts and try to tame them.
At UTN, people perform their Ugh Tasks independently, together.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s an Ugh Task? An Ugh Task is something you have to do, but which you&amp;rsquo;ve been putting off, such that now even the thought of it causes you to recoil a little with dread.
Maybe it&amp;rsquo;s an email you need to send, or an appointment you need to schedule. Maybe it&amp;rsquo;s a text you fear even reading, or something you said you&amp;rsquo;d have done long ago that you still haven&amp;rsquo;t finished. Often the ugh feeling that an Ugh Task elicits causes you to put off the task further, worsening the ugh feeling that it elicits &amp;ndash; an ugly downward cycle.&lt;/p&gt;
&lt;p&gt;Whatever your Ugh Task may be, it&amp;rsquo;s welcome at Ugh Task Night.&lt;/p&gt;
&lt;p&gt;A few more notes on the hosting of Ugh Task Night:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Should people RSVP? There is no &amp;ldquo;should&amp;rdquo;. And I don&amp;rsquo;t ask people to RSVP. The point isn&amp;rsquo;t to create more work for them. I do enjoy knowing who&amp;rsquo;s coming though, so RSVPing is totally optional.&lt;/li&gt;
&lt;li&gt;Can people invite their friends? This year I went with yes! I told folks they are welcome to invite others, &lt;em&gt;especially&lt;/em&gt; anyone they&amp;rsquo;ve been meaning to see for years but haven&amp;rsquo;t gotten around to reaching out to yet. i.e. In the spirit of the night, they can use Ugh Task Night as a tool to complete a possible social Ugh Task.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>The Dream of Just One Inbox</title>
      <link>https://davidbieber.com/snippets/2022-09-26-just-one-inbox/</link>
      <pubDate>Mon, 26 Sep 2022 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-09-26-just-one-inbox/</guid>
      
      <description>&lt;p&gt;Ideally I&amp;rsquo;d have just a single inbox, but in practice I have several.&lt;/p&gt;
&lt;p&gt;In fact, I have so many that I forget about some of them, and they fade away. Especially if we count all the different Slacks I&amp;rsquo;m part of, there&amp;rsquo;s no way I could keep up with all my inboxes. Here&amp;rsquo;s a quick list of the inboxes I&amp;rsquo;m currently trying to stay on top of: Personal email, Work email, Texts and Voicemail, a Twitter DMs, Facebook Messenger. In addition to these, there are more inboxes that I check but don&amp;rsquo;t really try to stay on top of: a shared Roam graph, some Slacks, and some Discords, and various social medias and news websites. Beyond these are the inboxes that I simply don&amp;rsquo;t think about these days: various forums, other Slacks and Discords, old game message boards. I&amp;rsquo;m blanking on the names of some of these, that&amp;rsquo;s how much they&amp;rsquo;ve faded.&lt;/p&gt;
&lt;p&gt;Even in my ideal world with a single inbox, there are different kinds of items that could reside in the inbox. I think the major designations are: requires attention, deferred, and indexed. Basically my thinking is, some items (i.e. emails, texts, voicemails, etc&amp;hellip; all the items that are directly specifically toward me that I want to read) go into the actual &lt;em&gt;inbox&lt;/em&gt; part of the inbox. They form a queue of things to process. I can process them by performing the task (responding, handling, etc) or by deferring (i.e. moving into a TODO list of sorts). Other items enter the inbox differently, and let&amp;rsquo;s take messages on a giant Slack channel as an example. These don&amp;rsquo;t need to be processed individually. They don&amp;rsquo;t even need to be processed in batch, to be honest. But it is nice to know that a whole batch of messages has arrived in the last week. I think my ideal would be that across many Slack channels and across many Slack groups and even across both Slacks and Discords and Google Chats, an overall digest of all the messages missed once a week or so would be nice. Eh, honestly that&amp;rsquo;s not necessary, the messages I have in mind are safe to ignore; it would be great if they remained searchable though.&lt;/p&gt;
&lt;p&gt;To summarize the different kinds of messages I&amp;rsquo;m thinking about, there are: (1) emails to me (each time I process the inbox, email email is an item to handle), (2) messages in large groups (these should be batched, and frozen at the time of consumption, OK to ignore lots; their presence should not indicate the need for a processing session), and (3) items I&amp;rsquo;ve saved for later (this is task tracking; tasks can appear in inbox if a system surfaces them to my attention, but can usually get out of the way).&lt;/p&gt;
&lt;p&gt;All the inboxes I try to stay on top of should be combined into one inbox and all messages therein fall into category 1. All the inboxes I check but don&amp;rsquo;t stay on top of should get batched and form category 2 (perhaps together constituting a single item of category 1). And any of these if ignored or deferred can become a category 3 item.&lt;/p&gt;
&lt;p&gt;RSS in some ways is an effort toward constructing a single inbox out of many disparate message locations. RSS readers, however, seem to have gone out of fashion. And even in their heyday, RSS feeds never handled emails, texts, phone calls, Twitter DMs, etc.&lt;/p&gt;
&lt;p&gt;Then there&amp;rsquo;s Sophia&amp;rsquo;s Unigraph. It shows promise as a potential unified inbox. I&amp;rsquo;ve seen as a demo it handles incoming tweets easily and is designed to be extensible to additional data sources. It wasn&amp;rsquo;t mature enough to take on One Inbox status last time I checked in on it, but perhaps with additional development it can reach that point.&lt;/p&gt;
&lt;p&gt;Bieber Bot does so much for me, and one of the things he does well is reducing the number of inboxes I have. Facebook Event invites, reminders about upcoming activities, and some other reminders all come through Bieber Bot, whereas without him I&amp;rsquo;d have to check Facebook and various spreadsheets and calendars as well. I already treat Facebook messenger as an inbox zero location, where all messages are processed, making Bieber Bot (who contacts me through FB Messenger) a good choice for surfacing such things. I actually treat FB Messenger more as an inbox-zero location than I do email (though to my delight I am at inbox zero for emails too these days), I guess in part because email gets a higher rate of messages making inbox zero harder to sustain.&lt;/p&gt;
&lt;p&gt;Suppose we were to build a new inbox, designed to be the One Inbox that replaces all others.
It would have to handle receiving messages in a boatload of different services and sending messages in all these services too.
It would have to handle easily adding new services that the developers didn&amp;rsquo;t anticipate.
Imagine using automation software like Browserflow to specify how the service should gather new items for an inbox.
For example, let&amp;rsquo;s say you want to integrate Roam or Twitter into your inbox, but the One Inbox developers haven&amp;rsquo;t heard of Roam or Twitter.
So you make a Browserflow flow that collects the inbox items from Roam or Twitter, and One Inbox runs it periodically on your behalf to gather new messages. You make a second Browserflow flow that shows One Inbox what it means to send messages through the new service.
Better even than that experience would be something like what the latest Adept AI demo is hinting at. In that direction, you don&amp;rsquo;t need to construct a program to show the One Inbox software how to receive and send messages; you just teach it with a combination of demonstration and natural language, and it can handle the rest from there.&lt;/p&gt;
&lt;p&gt;As we build the hypothetical One Inbox software, there are latency considerations. How long after a message is received on a service is it before the message appears in our One Inbox? Does this matter? Yes. The case for yes: you don&amp;rsquo;t want to miss items. The case for no: if we&amp;rsquo;re following an infrequent processing workflow, several minutes of latency doesn&amp;rsquo;t matter most of the time. Clearly the yeses have it.&lt;/p&gt;
&lt;p&gt;The software I use that comes closest to a One Inbox (besides Bieber Bot) right now is Ferdi. It doesn&amp;rsquo;t do anything intelligent to normalize incoming messages into a shared format across different messaging systems. That would be quite difficult (I think texts.com does this; I would like to try it, but haven&amp;rsquo;t yet). Instead, Ferdi just acts as a browser, loading all your different inboxes alongside one another. When described like this, it sounds silly and pointless &amp;ndash; &amp;ldquo;why not just use tabs in your browser?&amp;rdquo;. Well, the experience in Ferdi is different than just using tabs in your browser because it&amp;rsquo;s a separate application from your browser, it handles loading and unloading differently, and services are pinned with little icons for easy access. These are mostly superficial things, but they add up to an improved experience compared with keeping lots of tabs for lots of inboxes open in Chrome.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Logging into a Twitter App with OAuth</title>
      <link>https://davidbieber.com/snippets/2022-07-21-twitter-oauth-login/</link>
      <pubDate>Thu, 21 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-07-21-twitter-oauth-login/</guid>
      
      <description>&lt;p&gt;You can log into a Twitter app with OAuth using Twython. First, make sure you have twython pip installed (&lt;code&gt;pip install twython&lt;/code&gt;). Then, get the APP_KEY and APP_SECRET from the developer. This is labeled &amp;ldquo;API Key and Secret&amp;rdquo; on the app page at &lt;a href=&#34;https://developer.twitter.com/en/portal/apps/&#34;&gt;https://developer.twitter.com/en/portal/apps/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Next, run the following Python code:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import twython

client = twython.Twython(APP_KEY, APP_SECRET)
auth = client.get_authentication_tokens(callback_url=&#39;oob&#39;)

oauth_token = auth[&#39;oauth_token&#39;]
oauth_token_secret = auth[&#39;oauth_token_secret&#39;]
auth_url = auth[&#39;auth_url&#39;]

print(auth_url)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Navigate to the printed URL. Copy the pin.&lt;/p&gt;
&lt;p&gt;Then run:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;pin = &#39;YOUR_COPIED_PIN&#39;
client_full = twython.Twython(
    APP_KEY, APP_SECRET, oauth_token, oauth_token_secret)

auth = client_full.get_authorized_tokens(pin)

oauth_token = auth[&#39;oauth_token&#39;]
oauth_token_secret = auth[&#39;oauth_token_secret&#39;]
user_id = auth[&#39;user_id&#39;]
screen_name = auth[&#39;screen_name&#39;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Voila! oauth_token and oauth_token_secret hold the credentials for the logged in account.
The app is now authorized for your account using these credentials.
If the &amp;ldquo;app&amp;rdquo; is actually just you using Twython, construct a client with these credentials via:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;client = twython.Twython(APP_KEY, APP_SECRET, oauth_token, oauth_token_secret)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See also: past-me explains OAuth2 to myself 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-03-20-understanding-oauth2/&#34;&gt;in more detail here&lt;/a&gt;. It gets easier every time.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Hugo Layouts for this Website</title>
      <link>https://davidbieber.com/snippets/2022-07-20-hugo-layouts/</link>
      <pubDate>Wed, 20 Jul 2022 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-07-20-hugo-layouts/</guid>
      
      <description>&lt;p&gt;This is a note-to-self about how the code base for this website, davidbieber.com, is organized. There are several &amp;ldquo;layouts&amp;rdquo; files that live in the 
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/tree/master/hugo/layouts&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;hugo/layouts&lt;/a&gt; directories. This is what each of them does:&lt;/p&gt;
&lt;h4 id=&#34;hugolayouts_defaultlisthtmlhttpsgithubcomdbieberdavidbiebercomblobmasterhugolayouts_defaultlisthtml&#34;&gt;
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/blob/master/hugo/layouts/_default/list.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;hugo/layouts/_default/list.html&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/blob/master/hugo/layouts/_default/list.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;list.html&lt;/a&gt; defines how 
&lt;a href=&#34;https://davidbieber.com/snippets&#34;&gt;/snippets&lt;/a&gt;, 
&lt;a href=&#34;https://davidbieber.com/tags&#34;&gt;/tags&lt;/a&gt;, and each of the individual /tags/&lt;tag&gt; pages are rendered. Each of these pages holds a list of links, as well as a Discussion section.&lt;/p&gt;
&lt;h4 id=&#34;hugolayouts_defaultrssxmlhttpsgithubcomdbieberdavidbiebercomblobmasterhugolayouts_defaultrssxml&#34;&gt;
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/blob/master/hugo/layouts/_default/rss.xml&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;hugo/layouts/_default/rss.xml&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Defines the rss feeds for 
&lt;a href=&#34;https://davidbieber.com/snippets/index.xml&#34;&gt;snippets&lt;/a&gt; and for 
&lt;a href=&#34;https://davidbieber.com/posts/index.xml&#34;&gt;posts&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;hugolayoutspartialswidgetspageshtmlhttpsgithubcomdbieberdavidbiebercomblobmasterhugolayoutspartialswidgetspageshtml&#34;&gt;
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/blob/master/hugo/layouts/partials/widgets/pages.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;hugo/layouts/partials/widgets/pages.html&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Used to render the posts widget on the home page.&lt;/p&gt;
&lt;h4 id=&#34;hugothemesacademiclayoutssectionposthtmlusersdbiebercodegithubdbieberdavidbiebercomhugothemesacademiclayoutssectionposthtml&#34;&gt;
&lt;a href=&#34;https://davidbieber.com/Users/dbieber/code/github/dbieber/davidbieber.com/hugo/themes/academic/layouts/section/post.html&#34;&gt;/hugo/themes/academic/layouts/section/post.html&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Used to render the 
&lt;a href=&#34;https://davidbieber.com/posts&#34;&gt;/posts&lt;/a&gt; page. (Part of the theme.)&lt;/p&gt;
&lt;h4 id=&#34;hugolayoutspartialswidgetsportfoliohtmlhttpsgithubcomdbieberdavidbiebercomblobmasterhugolayoutspartialswidgetsportfoliohtml&#34;&gt;
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/blob/master/hugo/layouts/partials/widgets/portfolio.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;hugo/layouts/partials/widgets/portfolio.html&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Used to render the 
&lt;a href=&#34;https://davidbieber.com/projects&#34;&gt;/projects&lt;/a&gt; page.&lt;/p&gt;
&lt;h4 id=&#34;hugolayoutspartialscustom_jshtmlhttpsgithubcomdbieberdavidbiebercomblobmasterhugolayoutspartialscustom_jshtml&#34;&gt;
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/blob/master/hugo/layouts/partials/custom_js.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;hugo/layouts/partials/custom_js.html&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Embeds Firebase, Tumblr Embed Gist, JQuery, and React. Just the staples that appear on every page.&lt;/p&gt;
&lt;h4 id=&#34;hugolayoutspartialscustom_js_extrahtmlhttpsgithubcomdbieberdavidbiebercomblobmasterhugolayoutspartialscustom_js_extrahtml&#34;&gt;
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/blob/master/hugo/layouts/partials/custom_js_extra.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;hugo/layouts/partials/custom_js_extra.html&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Embeds page-specific JS bundles, e.g. Ask-Me-Anywhere, or margin-notes.js. The source for the custom JS bundles lives in 
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/tree/master/hugo/assets/js-src&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;assets/js-src&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;hugolayoutspartialsdiscussionhtmlhttpsgithubcomdbieberdavidbiebercomblobmasterhugolayoutspartialsdiscussionhtml&#34;&gt;
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/blob/master/hugo/layouts/partials/discussion.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;hugo/layouts/partials/discussion.html&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Embeds Discord on the page.&lt;/p&gt;
&lt;h4 id=&#34;hugolayoutspartialspage_headerhtmlhttpsgithubcomdbieberdavidbiebercomblobmasterhugolayoutspartialspage_headerhtml&#34;&gt;
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/blob/master/hugo/layouts/partials/page_header.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;hugo/layouts/partials/page_header.html&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Renders post header data, such as a chip if appropriate, the header image, and title and subtitle headers.&lt;/p&gt;
&lt;h4 id=&#34;hugolayoutspartialspage_footerhtmlhttpsgithubcomdbieberdavidbiebercomblobmasterhugolayoutspartialspage_footerhtml&#34;&gt;
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/blob/master/hugo/layouts/partials/page_footer.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;hugo/layouts/partials/page_footer.html&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Shows tags.
Includes the Discord discussion partial.
Includes 4 related pages in the footer.
Shows the author.&lt;/p&gt;
&lt;h4 id=&#34;hugolayoutspartialspage_metadata_authorshtmlhttpsgithubcomdbieberdavidbiebercomblobmasterhugolayoutspartialspage_metadata_authorshtml&#34;&gt;
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/blob/master/hugo/layouts/partials/page_metadata_authors.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;hugo/layouts/partials/page_metadata_authors.html&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Empty. Overwrites the equivalent file from the Academic theme preventing author metadata from rendering.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Future self, hope you find that useful!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Keyboards, keyboards, everywhere, and not a spot to think</title>
      <link>https://davidbieber.com/snippets/2022-07-20-keyboards-everywhere/</link>
      <pubDate>Wed, 20 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-07-20-keyboards-everywhere/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;You can also listen to this post.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;audio
controls
src=&#34;https://davidbieber.com/audio/keyboards-everywhere.m4a&#34;&gt;
Your browser does not support the &lt;code&gt;audio&lt;/code&gt; element.
&lt;/audio&gt;&lt;/p&gt;
&lt;p&gt;Keyboards, keyboards, everywhere, and not a spot to think.
This is take fourteen; I&amp;rsquo;ve tried to write this piece more times than I can count,
but I struggle to merge the various attempts into a coherent whole.
This is relevant, because its representative of an inability to focus on a large abstract piece of thought.&lt;/p&gt;
&lt;p&gt;This is the result of the state of our technology,
our collective technology,
how it strips us of our attention with notifications,
algorithms designed to keep us captive,
always coming back for more content,
personalized content, personalized content mixed with personalized ads.&lt;/p&gt;
&lt;p&gt;We all have smart phones and our eyes are glued to them.
We have computers in our pockets &amp;ndash; except they&amp;rsquo;re not in our pockets, they&amp;rsquo;re in our hands &amp;ndash; each with more compute than the Apollo mission computer.&lt;/p&gt;
&lt;p&gt;Where did it all go wrong?
There was such a great potential.
Computers &amp;ndash; personal computers &amp;ndash; had the potential to revolutionize the way that humanity thinks.
The potential looked a bit like this:&lt;/p&gt;
&lt;p&gt;Before, without computers, thinking was a slow process.
Computers can help.
They can allow us to think bigger, more elaborate, more complex thoughts than we could ever possibly have thought before.
With all the world&amp;rsquo;s information at our finger tips, we can dream truly grand dreams.
Individuals can realize visions that would have taken armies to even conceive of, let alone build, just decades earlier.
Computers, in short, were going to let us Think BIG.&lt;/p&gt;
&lt;p&gt;Where did it all go wrong? And what can we do to set it right?
Today, computers don&amp;rsquo;t let us think big thoughts. Instead, they inhibit thinking.
It takes time to think big thoughts.
But when your brain has been rewired to seek a dopamine hit each time its been without for more than sixteen seconds,
you don&amp;rsquo;t get the continuous uninterrupted time that&amp;rsquo;s required for proper big-thought thinking.&lt;/p&gt;
&lt;p&gt;Instead, you scroll a bit more on Facebook, you swipe on TikTok or Instagram or wherever.
You refresh the news.
The big idea your head is working on gets pushed back into the depths of the mind for a little longer.
Maybe it will poke its head out when you take a shower, or the next time you go on a nature hike.
(I shouldn&amp;rsquo;t have to include the word nature before hike in that sentence, yet here we are. Maybe the thought, the big thought, will come out in your next &lt;em&gt;nature&lt;/em&gt; hike.)&lt;/p&gt;
&lt;p&gt;I built something.
That&amp;rsquo;s part of why I&amp;rsquo;m writing this piece. I want to show off the thing I built.
It&amp;rsquo;s meant to help with the sort of problem I&amp;rsquo;m describing &amp;ndash; the inability to think big thoughts, because of the incessant attraction of the internet&amp;rsquo;s many distractions.&lt;/p&gt;
&lt;p&gt;The thing I built, it&amp;rsquo;s called Go Note Go, and it&amp;rsquo;s just a keyboard, with no monitor attached.
You can type on it &amp;ndash; that&amp;rsquo;s what I&amp;rsquo;m doing now &amp;ndash; or you can talk to it.
And whatever you type or say, once the keyboard gets in range of wifi, will be uploaded to wherever you keep your notes and writings.&lt;/p&gt;
&lt;p&gt;The beauty of this keyboard of course is the absence of the screen.
There are no distractions when typing on this keyboard.
You&amp;rsquo;re just alone with your thoughts.&lt;/p&gt;
&lt;p&gt;You can&amp;rsquo;t even see what you&amp;rsquo;re typing.
For many people this is a turn off &amp;ndash; how can you type if you can&amp;rsquo;t see what you&amp;rsquo;re typing?&lt;/p&gt;
&lt;p&gt;Well, you know what you&amp;rsquo;re typing. You get used to not seeing it pretty quickly.
Sure, you make more typos than you would if you had a screen.
But at the same time, you are freed from having to avoid typos.
You are freed from thinking about revising, wordsmithing, editing of any kind, because you can&amp;rsquo;t go back and you can&amp;rsquo;t change what you&amp;rsquo;ve done.
And so you press on, adding new content, thinking new thoughts.&lt;/p&gt;
&lt;p&gt;The Go Note Go keyboard works in the wilderness; it works if you&amp;rsquo;re camping or hiking, certainly.
You can also bring it with you to bed, and type as you drift off to sleep.
You can even take a waterproof version into the shower with you, and capture your shower thoughts.&lt;/p&gt;
&lt;p&gt;Does this idea live dangerously at the edge of allowing you to free your mind to think, and glorifying productivity at the expense of even being free while you sleep and shower? Yes, it sits precisely on that knife edge. It is not a panacea.&lt;/p&gt;
&lt;p&gt;You can make this keyboard more distracting than Reddit itself, if you allow yourself too.
You can spend hours typing when you could be sleeping, or showering when you could be moving on to breakfast or reading the news, because the keyboard lets you pontificate productively rather than wash your hair and be done.&lt;/p&gt;
&lt;p&gt;So, Go Note Go with caution, and then reap the rewards: a place to think.
A place to think, unencumbered by ads, or messages from friends, or the possibility of an update or an article to read.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve placed these Go Note Go keyboards all throughout my apartment.
I have one at each place where I might work, so that I can type thoughts without needing to switch to a text editor on my computer.
I simply turn to the Go Note Go and type.
I have one in my bed, and one in my car, which I can talk to as I drive.
If I go camping, one goes into the tent with me.&lt;/p&gt;
&lt;p&gt;Now I have spaces to think everywhere.&lt;/p&gt;
&lt;p&gt;The title of this post is a play on the classic verse from The Rime of the Ancient Mariner.&lt;/p&gt;
&lt;p&gt;Keyboards, keyboards, everywhere, and not a space to think.&lt;/p&gt;
&lt;p&gt;This line tells us of the failed promise of computers.
They promised us a place to think:
a great tool to allow us to think greater, bigger thoughts than before.
And computers proliferated, both because of the good they do, as well as their siren song.&lt;/p&gt;
&lt;p&gt;So the world we live in lives up to that line now.
There are keyboards everywhere, but they are all attached to monitors, attached to the internet, attached to our pockets and our hands and our minds.
And they leave us with no place to think.
They are water, and we are at sea.&lt;/p&gt;
&lt;p&gt;So, I present Go Note Go.
It does not fight the tide.
It adds more keyboards, not fewer.
But, in doing so, so long as we proceed with caution,
it reclaims a little bit of our space to think.&lt;/p&gt;
&lt;p&gt;Instructions for how to make your own Go Note Go are available 
&lt;a href=&#34;https://github.com/dbieber/GoNoteGo&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;here&lt;/a&gt;.
To learn more about what it does, it&amp;rsquo;s features and all that, to help you think, 
&lt;a href=&#34;https://davidbieber.com/projects/go-note-go/&#34;&gt;click here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now, go forth into nature, keyboard or no, and think a little.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Focus on the Task of Focusing on the Task (Incomplete)</title>
      <link>https://davidbieber.com/snippets/2022-07-13-focus-on-the-task/</link>
      <pubDate>Wed, 13 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-07-13-focus-on-the-task/</guid>
      
      <description>&lt;p&gt;Focus on the task of focusing on the task.
If your breath seems a bit bland to get started, try &amp;ldquo;focus on &lt;em&gt;this&lt;/em&gt;&amp;rdquo; instead.
It&amp;rsquo;s all the same in the end, anyway.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The Medical Test Paradox Paradox</title>
      <link>https://davidbieber.com/snippets/2022-07-12-medical-test-paradox-paradox/</link>
      <pubDate>Tue, 12 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-07-12-medical-test-paradox-paradox/</guid>
      
      <description>&lt;p&gt;In this snippet we&amp;rsquo;re going to introduce the Medical Test Paradox &lt;em&gt;Paradox&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;First, you may already be familiar with the 
&lt;a href=&#34;https://www.youtube.com/watch?v=lG4VkPoG3ko&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Medical Test Paradox&lt;/a&gt;. It&amp;rsquo;s a popular recreational math problem that teaches Bayes&#39; theorem and the importance of base rates. It goes like this.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Suppose 1 in 10000 people have a certain disease, and there is a medical test that is 99% accurate. This means that if you do have the disease, the test comes back positive with 99% probability, and if you do not have the disease, the test comes back negative with 99% probability. It is wrong 1% of the time.&lt;/p&gt;
&lt;p&gt;If your test result comes back positive, what&amp;rsquo;s the probability that you have the disease?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;details&gt;
  &lt;summary&gt;Spoiler: Expand this to see the solution.&lt;/summary&gt;
&lt;p&gt;The classic solution proceeds as follows.&lt;/p&gt;
&lt;p&gt;Let $D=\text{yes}$ be the event where you have the disease.
Let $T=\text{positive}$ be the event where the test comes back positive.&lt;/p&gt;
&lt;p&gt;Using this notation, we want to find $P(D=\text{yes} | T=\text{positive})$.
We proceed by Bayes&#39; theorem.&lt;/p&gt;
&lt;p&gt;$P(D=\text{yes} | T=\text{positive}) = \frac{P(T=\text{positive} | D = \text{yes})P(D = \text{yes})}{P(T = \text{positive})}$
$$= \frac{P(T=\text{positive} | D = \text{yes})P(D = \text{yes})}{P(T=\text{positive} | D = \text{yes})P(D = \text{yes}) + P(T=\text{positive} | D = \text{no})P(D = \text{no})}$$
$$= \frac{0.99 \cdot \frac{1}{10000}}{0.99 \cdot \frac{1}{10000} + 0.01 \cdot \frac{9999}{10000}}$$
$$= 0.009803 \approx \fbox{1%}$$&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;It&amp;rsquo;s a &amp;ldquo;paradox&amp;rdquo; only because the answer is surprisingly low. If you haven&amp;rsquo;t solved it or peeked at the solution yet, have a guess at the rough answer before you look at the true one.&lt;/p&gt;
&lt;p&gt;Now, on to the Medical Test Paradox Paradox. The Medical Test Paradox Paradox asks: given that tests for &lt;em&gt;actual&lt;/em&gt; diseases are generally much &lt;em&gt;less&lt;/em&gt; than 99% accurate, and given that prevalences for &lt;em&gt;actual&lt;/em&gt; diseases are 
&lt;a href=&#34;https://www.medicalhomeportal.org/diagnoses-and-conditions/diagnosis-prevalence-list&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;frequently&lt;/a&gt; &lt;em&gt;less&lt;/em&gt; than 1 in 10000, &lt;em&gt;how is it that doctors use tests to diagnose people with these diseases, frequently literally saving their lives, &lt;strong&gt;all the time&lt;/strong&gt;?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This is meant to be treated as a serious question, a puzzle if you will. So take a minute and think about it, and attempt to provide a serious answer.&lt;/p&gt;
&lt;p&gt;Like the Medical Test Paradox, the Medical Test Paradox &lt;em&gt;Paradox&lt;/em&gt; is of course not a true paradox. There is a simple explanation that accounts for an apparently paradoxical discrepancy. First, why does it look like a paradox at all?&lt;/p&gt;
&lt;p&gt;Take any real disease with prevalence roughly 1 in 10000 (e.g. 
&lt;a href=&#34;[frequently]%28https://www.medicalhomeportal.org/diagnoses-and-conditions/diagnosis-prevalence-list%29&#34;&gt;from this list&lt;/a&gt;). These are real diseases affecting real people. The best tests for that disease likely has less than 99% accuracy.
So even if you test positive for the disease, Bayes&#39; theorem suggests the probability you have the disease remains less than 1%. How are people then getting diagnosed with the disease at all? It seems as if doctors would have no way to conclude with greater than 1% certainty that you have the disease, even if your test comes back positive. You don&amp;rsquo;t want to give someone a treatment with side effects if there&amp;rsquo;s only a one percent chance they&amp;rsquo;re actually afflicted with the disease in question.&lt;/p&gt;
&lt;details&gt;
  &lt;summary&gt;Expand to see the rest of the snippet. We discuss resolutions to the paradox.&lt;/summary&gt;
&lt;p&gt;The Medical Test Paradox assumes that prior to taking the medical test, the probability that you have the disease is given by the disease&amp;rsquo;s prevalence, i.e. 1 in 10000. This is true if the medical test is being administered to random members of the population.
However, usually there is a &lt;em&gt;reason&lt;/em&gt; for administering a medical test.
Common reasons you might take a medical test include (a) you are showing symptoms or (b) exposure to a pathogen.
In these scenarios, the prior probability that you have the disease is higher than the disease&amp;rsquo;s prevalence.&lt;/p&gt;
&lt;p&gt;Doctors aren&amp;rsquo;t just administering random tests to random people.
They are administering tests as part of a differential where the test is likely to distinguish between a small number of reasonable alternative hypotheses that could explain your symptoms, generally each with a prior far exceeding 1 in 10000 (I&amp;rsquo;d estimate values between 1 in 10 and 1 in 3 are more common, but of course it varies according to the specifics of the situation).
The priors are higher than the candidate diseases&#39; prevalence because your symptoms already indicate that you have &lt;em&gt;something&lt;/em&gt;, even though they don&amp;rsquo;t fully narrow down what it is you have.&lt;/p&gt;
&lt;p&gt;This &lt;em&gt;reason for administering the test&lt;/em&gt; resolves the Medical Test Paradox Paradox.&lt;/p&gt;
&lt;details&gt;
  &lt;summary&gt;Does this change how we think about the original Medical Test Paradox?&lt;/summary&gt;
&lt;p&gt;I think it does. Now, when asked &amp;ldquo;If your test result comes back positive, what&amp;rsquo;s the probability that you have the disease?&amp;rdquo;, I no longer think the appropriate answer is 1%. Instead, the appropriate response is &amp;ldquo;Why did I take the test? Was I exposed? Do I have symptoms? Or was I participating in an experimental trial?&amp;rdquo; Only if there was no reason for taking the test is the answer 1% appropriate. If there was a good reason, the probability is likely much higher than 1%.&lt;/p&gt;
&lt;/details&gt;
&lt;/details&gt;
</description>
    </item>
    
    <item>
      <title>Dealing with Giant Group Chats</title>
      <link>https://davidbieber.com/snippets/2022-07-05-giant-group-chats/</link>
      <pubDate>Tue, 05 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-07-05-giant-group-chats/</guid>
      
      <description>&lt;p&gt;Sometimes &amp;ndash; usually because of Alex K Chen &amp;ndash; I am added to a giant group chat (GGC).
Today it was a 200+ person highly active chat with folks talking about AI programming tools, aging, and movies.
I love being added to such a chat. It makes me feel thought of, and my opinions respected. So, do keep adding me to GGCs.
However, with being added to a GGC comes some struggles. I haven&amp;rsquo;t fully figured out how to handle a GGC just yet.&lt;/p&gt;
&lt;p&gt;I think some people handle these situations in a more natural way than myself. Here&amp;rsquo;s what I imagine. They&amp;rsquo;re doing something else on the computer, messages are open in the background or in a side window. If they have a conversation-adjacent thought, they share it. If they see a message that looks interesting, they read it. Otherwise, they do their other activities and get on with their life.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If they have a conversation-adjacent thought, they share it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This part is Struggle #1.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If they see a message that looks interesting, they read it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This part is Struggle #2.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&#34;struggle-1-sharing-thoughts-casually-in-a-200-person-setting&#34;&gt;Struggle #1: Sharing thoughts casually in a 200+ person setting&lt;/h3&gt;
&lt;p&gt;Why is this a struggle? I think slowly. I edit. I rethink relevance as the conversation moves away.
The hypothetical person who handles GCCs as described above &amp;ldquo;just&amp;rdquo; types and hits enter, relatively unencumbered.
I think about the permanence of putting something on the internet.
I think about confidentiality of work-adjacent stuff.
I think about whether what I&amp;rsquo;m saying is true, and about how true it is.
This kind of thought can make participation a challenge.&lt;/p&gt;
&lt;h3 id=&#34;struggle-2-staying-abreast-of-200-messages-per-hour&#34;&gt;Struggle #2: Staying abreast of 200 messages per hour&lt;/h3&gt;
&lt;p&gt;I don&amp;rsquo;t want to read all these messages.
They glimmer and my attention is drawn to them, but that doesn&amp;rsquo;t reflect my conscious decision making.
I&amp;rsquo;d much rather read a summary of the messages or a digest of the topics discussed once a week or so.
Then, only if a topic of interest was discussed, I might want to dive deeper and read the individual messages, and
contemplate leaving a reply.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&#34;tooling-for-struggle-1&#34;&gt;Tooling for Struggle #1&lt;/h3&gt;
&lt;p&gt;tl;dr Draft messages outside of conversation UI. Use &amp;ldquo;approve for dealyed send&amp;rdquo; model for sending messages.&lt;/p&gt;
&lt;p&gt;Struggle #1 is a personal psychological struggle.
It isn&amp;rsquo;t first and foremost something for which tooling seems relevant.
If I&amp;rsquo;m not comfortable sharing something with 200 people in a chat, why would tooling change that?
Well, as I&amp;rsquo;ve learned from adding 
&lt;a href=&#34;https://davidbieber.com/post/2022-01-08-new-messager-setup/&#34;&gt;Messager in Go Note Go&lt;/a&gt; tooling can actually make a huge difference in this type of space.
If instead of feeling like I&amp;rsquo;m sending a message to a massive group, I instead feel like I&amp;rsquo;m writing a draft of my thoughts, something I&amp;rsquo;ll maybe send later but maybe not, suddenly it becomes so much easier to write.
And then, once it&amp;rsquo;s written, it also becomes much easier to send.
This is the same lesson I&amp;rsquo;ve learned over and over with snippets since I initially decided to set up this system as 
&lt;a href=&#34;https://davidbieber.com/snippets/2019-12-30-writing-for-no-audience/&#34;&gt;writing for no audience&lt;/a&gt; back in 2019.&lt;/p&gt;
&lt;p&gt;So, what would the tooling look like for dealing with Struggle #1 in GGCs?
I would click a message to start drafting a response,
it would copy the message and context into an editor &amp;ndash; Roam Research, say &amp;ndash; and maybe even stick in the template for writing a snippet.
Then, completely outside the context of the group thread I could compose my thoughts.
If I decide to share it back to the group, great.
If I decide to instead post that thought as a snippet, great.
And if it remains relegated to my notes forever and never sees the light of day, that&amp;rsquo;s a fine outcome too.&lt;/p&gt;
&lt;p&gt;[Aside: The acceptability of that outcome is what makes the writing easier. The very possibility of that outcome diminishes the possibility of that outcome by making the other outcomes more likely. It&amp;rsquo;s the opposite of a self-fulfilling prophecy. A self-fulfilling prophesy is an expectation whose existence leads to its own fulfillment; this is an expectation whose very existence works to prevent its fulfillment.]&lt;/p&gt;
&lt;p&gt;One of the lessons I learned from my Go Note Go messager-queue was the value of the &amp;ldquo;approve for delayed send&amp;rdquo; model.
Psychologically it was easier for me to mark a message as approved for sending, and have an automated system later send the message on my behalf once it was approved, rather than directly sending it myself.
Marking something as approved for sending (1) admits the possibility that I make further revisions to the message, and (2) internally relieves myself of some of the responsibility of sending the message. Of course, I am still fully responsible for the message and I accept this responsibility, but nevertheless that perception of decreased responsibility is a relaxing feeling that makes message sending easier.
It also (3) prevents me from actively waiting for replies to come it, a behavior I&amp;rsquo;d like to avoid. It does this because my messages go out without my awareness in the moment, so I cannot sit refreshing or watching for new messages. This way I don&amp;rsquo;t need to expend effort diverting my attention away from waiting for messages; my own unawareness has taken care of this for me.
So, having this &amp;ldquo;approve for delayed send&amp;rdquo; model for dealing with GGCs would be appreciated.&lt;/p&gt;
&lt;h3 id=&#34;tooling-for-struggle-2&#34;&gt;Tooling for Struggle #2&lt;/h3&gt;
&lt;p&gt;Struggle #2 has psychological components, but is also more directly about capabilities.&lt;/p&gt;
&lt;p&gt;The psychological bit:
Keeping up with 200 messages per hour isn&amp;rsquo;t even desirable. Why? It&amp;rsquo;s not that it&amp;rsquo;s a lot of noise &amp;ndash; though sometimes there is a lot of noise.
But even when there&amp;rsquo;s a lot of high quality interesting fun messages, it&amp;rsquo;s not stuff I&amp;rsquo;m actively looking to read or learn about or people that I&amp;rsquo;m choosing to keep in touch with. Instead, it&amp;rsquo;s whatever the group collectively has steered toward.
I&amp;rsquo;d rather be more intentional about what I read and discuss, rather than being at the whims of 200+ people, many of whom I haven&amp;rsquo;t met.
However, there is tension between that desire for intentionality and the desire to hear folks&#39; interesting ideas and share my own.
Adding to the tension further is a natural inclination toward reading messages as they come in, because they&amp;rsquo;re attention-grabbing even if they aren&amp;rsquo;t where I&amp;rsquo;d like to place my focus.&lt;/p&gt;
&lt;p&gt;The capabilities bit:
Even if I decided I did want to stay abreast of the conversation, there&amp;rsquo;s simply too much to reasonably process.
People are discussing topics about which I have a lot to learn.
I don&amp;rsquo;t have the bandwidth to think deeply &amp;ndash; or even shallowly &amp;ndash; about what folks are saying, while also maintaining normal human functions.&lt;/p&gt;
&lt;p&gt;So, what tooling can help?&lt;/p&gt;
&lt;p&gt;Summarization:
A machine learning system that categorizes messages by topic would be super helpful.
It could send a weekly digest listing the topics discussed, and clicking on a topic could bring me to a summary of the messages, with the option to drill down into the individual messages.&lt;/p&gt;
&lt;p&gt;Notification settings:
Right now I&amp;rsquo;ve simply turned off all notifications. If I could turn back on notifications for specific topics, that would be nice. E.g. &amp;ldquo;notify me if people start talking about programming tools again, but only if we haven&amp;rsquo;t talked about programming tools in at least a day since the last time you notified me.&amp;rdquo; This type of notification seems straightforward to build combining my Messager system with LLMs. Perhaps I&amp;rsquo;ll give it a go.&lt;/p&gt;
&lt;p&gt;Messenger UI: Even with notifications disabled, GGCs appear first in my list of Messenger chats because FB orders them by message recency, and GGCs always have a recent message. I&amp;rsquo;d prefer a way to keep them out of this default view, so I can see genuine conversations with individual people in their place.&lt;/p&gt;
&lt;p&gt;Browsing UI: The existing UI is unhelpful for trying to get an overview of the conversation. There&amp;rsquo;s a lot of whitespace, so only a few messages are visible at once. Replies for different topics are all mixed together.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;If you&amp;rsquo;re working on anything like the toolings mentioned here, don&amp;rsquo;t hesitate to get in touch. There&amp;rsquo;s a Discussions section below, or feel free to ping me in a GGC!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Using Discord for my website&#39;s comments section</title>
      <link>https://davidbieber.com/snippets/2022-06-21-using-discord/</link>
      <pubDate>Tue, 21 Jun 2022 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-06-21-using-discord/</guid>
      
      <description>&lt;p&gt;Yesterday I added &amp;ldquo;Discussion&amp;rdquo; sections to all the snippets and posts on my website.
I wrote 
&lt;a href=&#34;https://davidbieber.com/snippets/2022-06-20-chat-by-tag&#34;&gt;a snippet about it&lt;/a&gt; as I was doing it.
The project morphed considerably during the writing of that snippet.
So, today, I&amp;rsquo;m putting together a shorter snippet that says what I actually did.&lt;/p&gt;
&lt;p&gt;I created a Discord server for this website (I invite you to 
&lt;a href=&#34;https://discord.gg/NJ7ufFuEMa&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;join the Discord here&lt;/a&gt;.)
Then, I used widgetbot.io to embed the Discord server all throughout my website.
Every snippet, every post, every tags page, and the 
&lt;a href=&#34;https://davidbieber.com/snippets/&#34;&gt;overall snippets&lt;/a&gt; and 
&lt;a href=&#34;https://davidbieber.com/tags/&#34;&gt;overall tags&lt;/a&gt; pages all got Discussion sections.&lt;/p&gt;
&lt;p&gt;On the Discord server, I made one channel per &lt;em&gt;tag&lt;/em&gt; on my website.
The Discussion section for a given page shows the channel for the first tag on that page.
This makes it more likely that you&amp;rsquo;ll encounter a bit of conversation compared with their being a single comments section per page on the site, given the modest level of traffic we&amp;rsquo;re seeing here.&lt;/p&gt;
&lt;p&gt;Go ahead and expand the Discussion section below.
Say hi.
There&amp;rsquo;s no need to log in; you can be completely anonymous if desired, or use your real name.
Please just be respectful of the space and of others.&lt;/p&gt;
&lt;p&gt;See you in the chat.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Chat by Tag</title>
      <link>https://davidbieber.com/snippets/2022-06-20-chat-by-tag/</link>
      <pubDate>Mon, 20 Jun 2022 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-06-20-chat-by-tag/</guid>
      
      <description>&lt;p&gt;I don&amp;rsquo;t have a comments section on my website, but I do like when people reach out to me by email.
I am thinking about an idea for adding chat to my website, but the experience I have in mind is different from any chat or comments section that I&amp;rsquo;ve seen before.
Here&amp;rsquo;s what I&amp;rsquo;m thinking about and why &amp;ndash; please do let me know if it exists.&lt;/p&gt;
&lt;p&gt;At the end of each snippet there would be a badge for each tag associated with that snippet, as there already is today.
Each badge would indicate that there is a chat thread available for that tag.
E.g. it would show the number of active users and amount of recent activity in the chatroom.
Clicking the badge would take you to the tag&amp;rsquo;s page, which would list all the snippets having that tag.
The tag page would now also house the tag&amp;rsquo;s chat thread.&lt;/p&gt;
&lt;p&gt;On the tag page you could engage in real time chat, and your messages would stay up for a week (or until I take them down, in the case of spam).&lt;/p&gt;
&lt;p&gt;My website is not particularly heavily trafficked, but enough people email me about the things I write that this features interests me.
I don&amp;rsquo;t envision any of the chats having any content the majority of the time.
I would set the lifetime of a message to just one week.
Between the low traffic and ephemerality of the messages, most of the chats would be empty most of the time.
I would set up email notifications for myself though, so that I know if someone does post a message.
So at the very least, I could reply, even if few others see the messages.&lt;/p&gt;
&lt;p&gt;As often happens when writing a snippet about an idea I&amp;rsquo;ve had, I start looking into how to implement it concurrently with writing it.
I&amp;rsquo;ve looked at Rocket.Chat, Slack, and Discord, and am currently investigating whether using widgetbot.io to provide access to a Discord server might be a solid solution here.
What follows is my initial attempt at including Discord directly in this snippet.&lt;/p&gt;
&lt;details id=&#34;chat-details-inline&#34;&gt;
  &lt;summary markdown=&#34;span&#34;&gt;Expand this to see the embedded chat.&lt;/summary&gt;
  &lt;widgetbot
    server=&#34;695290335823265862&#34;
    channel=&#34;988521423603654686&#34;
    width=&#34;100%&#34;
    height=&#34;600&#34;&gt;
  &lt;/widgetbot&gt;
&lt;/details&gt;&lt;br/&gt;
&lt;p&gt;It seems to be working quite well.&lt;/p&gt;
&lt;p&gt;So, given that this tool is readily available, I will compromise on my original vision some.
I think what I&amp;rsquo;ll do now is (1) find a way to lazily load the chat so people who don&amp;rsquo;t want to deal with it aren&amp;rsquo;t bothered by it,
and then (2) I&amp;rsquo;ll add it (behind an expandable section) to every snippet and every tags page.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll set up a Discord server with one channel per tag. On the tag pages, the chat will default open to that tag&amp;rsquo;s channel.
On the individual snippets, the chat will default open to the first tag present on the page.
Users can easily switch to other channels if they so desire.&lt;/p&gt;
&lt;p&gt;So, how to lazy load? This turned out to be simple enough to implement quite quickly. I added some JavaScript to the page that loads the widgetbot JavaScript only when the collapsed chat is expanded. It looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script&amp;gt;
let chatLoaded = false;
const details = document.querySelector(&#39;#chat-details&#39;);
details.addEventListener(&amp;quot;toggle&amp;quot;, event =&amp;gt; {
  if (details.open &amp;amp;&amp;amp; !chatLoaded) {
    const script = document.createElement(&#39;script&#39;);
    script.src = &amp;quot;https://cdn.jsdelivr.net/npm/@widgetbot/html-embed&amp;quot;;
    document.head.appendChild(script);
    chatLoaded = true;
  }
});
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(Why am I showing this code? It is not germane to the story. A: This is a snippet, and so I guess I do not curate the content like I would if the goal were a proper story. It&amp;rsquo;s meant for future me as much as for anyone else.)&lt;/p&gt;
&lt;script&gt;
let chatLoadedInline = false;
const detailsInline = document.querySelector(&#39;#chat-details-inline&#39;);
detailsInline.addEventListener(&#34;toggle&#34;, event =&gt; {
  if (detailsInline.open &amp;&amp; !chatLoadedInline) {
    const script = document.createElement(&#39;script&#39;);
    script.src = &#34;https://cdn.jsdelivr.net/npm/@widgetbot/html-embed&#34;;
    document.head.appendChild(script);
    chatLoadedInline = true;
  }
});
&lt;/script&gt;
&lt;p&gt;Having set up the lazy loading, the next step was to create channels for each of the tags on my site.
There are a lot of tags, so I used Browserflow to do this quickly. A joy as always.&lt;/p&gt;
&lt;p&gt;Finally, I&amp;rsquo;ll have to update my website so that the appropriate chat gets added to the appropriate page. (I&amp;rsquo;m back, and that&amp;rsquo;s done now :).)&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve tagged this post with &amp;ldquo;Ask Me Anywhere&amp;rdquo; because, like my original Ask Me Anywhere ideas, this is about allowing for more direct engagement between me and people on the site. I&amp;rsquo;ve also tagged this &amp;ldquo;Snippets&amp;rdquo;, because it&amp;rsquo;s primarily about a change to the snippets section of my website, and &amp;ldquo;Browserflow&amp;rdquo; because Browserflow was a joy to use for setting up this new system.&lt;/p&gt;
&lt;p&gt;At this point, I&amp;rsquo;m concluding the snippet. The system is up and running. That was certainly not my expectation when I started writing this, but I&amp;rsquo;m delighted by the progress I made.&lt;/p&gt;
&lt;details&gt;
  &lt;summary&gt;As an aside, David, expand this for a reminder of how to add a new tag.&lt;/summary&gt;
There will be some maintenance work necessary whenever I add a snippet with a new tag. Let me summarize the maintenance for myself here for easy reference:
&lt;ol&gt;
&lt;li&gt;Create a new channel in the Discord.&lt;/li&gt;
&lt;li&gt;Add the tag name and channel id to the map at the top of the 
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/blob/master/hugo/layouts/partials/discussion.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;discussion.html partial&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The site won&amp;rsquo;t fail to build if you forget to do this; it will just have a broken chat section.&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;That should be it. See you in the chats!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Taking Your Co-Working Sessions to the Next Level</title>
      <link>https://davidbieber.com/snippets/2022-05-01-coworking-sessions/</link>
      <pubDate>Sun, 01 May 2022 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-05-01-coworking-sessions/</guid>
      
      <description>&lt;p&gt;I enjoy hosting co-working sessions.
Pre-pandemic I used to just go to a coffee shop and invite people to join me.
Now, trying to limit exposure to strangers, I&amp;rsquo;m having working sessions at my apartment.&lt;/p&gt;
&lt;p&gt;These working sessions are gatherings intended for people to independently work on hobbies, side projects, work, homework, future startups, catching up on emails, reading, whatever. Having other people around can make working more fun and make it easier to stay focused.&lt;/p&gt;
&lt;p&gt;This is a list of ideas about how to take these co-working sessions to the next level.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;External monitors&lt;/li&gt;
&lt;li&gt;Cords and cables for charging&lt;/li&gt;
&lt;li&gt;Food prepared in advance&lt;/li&gt;
&lt;li&gt;Go Note Gos everywhere&lt;/li&gt;
&lt;li&gt;Pomodoro timers&lt;/li&gt;
&lt;li&gt;Time for people to declare what they&amp;rsquo;re working on&lt;/li&gt;
&lt;li&gt;Dedicated time for chitchat&lt;/li&gt;
&lt;li&gt;A firm stance on allowing people to get to work if chitchat lingers more than several minutes outside of a planned time.&lt;/li&gt;
&lt;li&gt;Add a shared chat room for people to send non-interrupting messages to the whole group.
Useful for coordinating going out for lunch taking breaks etc.&lt;/li&gt;
&lt;li&gt;Clear policy on inviting others&lt;/li&gt;
&lt;li&gt;Adequate comfortable space for everyone, including spaces just move around and switch positions&lt;/li&gt;
&lt;li&gt;Learn to make coffee.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;Let&amp;rsquo;s do some taxonomizing!&lt;/p&gt;
&lt;p&gt;Some of these ideas are about providing technology:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;External monitors&lt;/li&gt;
&lt;li&gt;Cords and cables&lt;/li&gt;
&lt;li&gt;Go Note Gos everywhere&lt;/li&gt;
&lt;li&gt;Chat room for non-interrupting messages&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some are about providing nutrition:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Food prepared in advance&lt;/li&gt;
&lt;li&gt;Learn to make coffee.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some are about establishing social norms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pomodoro timers&lt;/li&gt;
&lt;li&gt;Time for people to declare what they&amp;rsquo;re working on&lt;/li&gt;
&lt;li&gt;Dedicated time for chitchat&lt;/li&gt;
&lt;li&gt;A firm stance on allowing people to get to work&lt;/li&gt;
&lt;li&gt;Chat room for non-interrupting messages&lt;/li&gt;
&lt;li&gt;Clear policy on inviting others&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some are about making people comfortable:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Adequate comfortable space for everyone&lt;/li&gt;
&lt;li&gt;Both the food ones&lt;/li&gt;
&lt;li&gt;External monitors and Cords and cables&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;I&amp;rsquo;m not sold these are &lt;em&gt;all&lt;/em&gt; good ideas
(e.g. pomodoro timers can be disruptive, and I considered putting &lt;em&gt;light music&lt;/em&gt; on the list but decided against it),
but I think that by implementing several of these ideas I can make my working sessions a little more welcoming and enjoyable for all involved.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Additional ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Inviting people in advance&lt;/li&gt;
&lt;li&gt;Having about 6 people in total&lt;/li&gt;
&lt;li&gt;Inviting people around a theme&lt;/li&gt;
&lt;li&gt;Sharing updates at the end&lt;/li&gt;
&lt;li&gt;Planning a working session in conjunction with another activity like a hike or dinner&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>My strategies for keeping my attention</title>
      <link>https://davidbieber.com/snippets/2022-03-18-attention-strategies/</link>
      <pubDate>Fri, 18 Mar 2022 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-03-18-attention-strategies/</guid>
      
      <description>&lt;p&gt;Lately I&amp;rsquo;ve sometimes had trouble focusing. My attention will sometimes drift to one of the internet&amp;rsquo;s 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-10-01-infinite-distractions-and-getting-a-good-sear/&#34;&gt;infinite distractions&lt;/a&gt;.
I&amp;rsquo;ve made a list of strategies I use to combat this, to better align my attention with my intentions.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Using an outliner like Roam Research (see 
&lt;a href=&#34;https://davidbieber.com/tags/roam-research&#34;&gt;these snippets&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Working with another person (e.g. pair programming)&lt;/li&gt;
&lt;li&gt;Working with another person present (e.g. independent coworking)&lt;/li&gt;
&lt;li&gt;Running a 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-01-09-mobile-distraction-detection-at-last/&#34;&gt;&amp;ldquo;distraction detection&amp;rdquo; program&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Mentally noting the distraction-kind and returning my attention&lt;/li&gt;
&lt;li&gt;Keeping 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-07-08-phone-in-kitchen/&#34;&gt;my phone in my kitchen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Writing on 
&lt;a href=&#34;https://davidbieber.com/projects/go-note-go/&#34;&gt;Go Note Go&lt;/a&gt;, my headless keyboard&lt;/li&gt;
&lt;li&gt;Attending meetings/talks in &amp;ldquo;clamshell mode&amp;rdquo; (laptop closed, no keyboard or mouse available)&lt;/li&gt;
&lt;li&gt;Making TODO lists&lt;/li&gt;
&lt;li&gt;And explicitly writing down the ^^active TODO^^&lt;/li&gt;
&lt;li&gt;Going to sleep at a &lt;strong&gt;specific&lt;/strong&gt; time (e.g. 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-04-20-sleep-no-snippet/&#34;&gt;10:10pm&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Exercising regularly (or at least 
&lt;a href=&#34;https://davidbieber.com/tags/table-tennis/&#34;&gt;aiming to&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Stopping watching TV in the middle of an episode (ends of episodes are more addicting)&lt;/li&gt;
&lt;li&gt;50 minute working sessions (e.g. 
&lt;a href=&#34;https://focusmate.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;focusmate.com&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Stretching&lt;/li&gt;
&lt;li&gt;Taking short deliberate breaks&lt;/li&gt;
&lt;li&gt;Using Pomodoro timers for working sessions&lt;/li&gt;
&lt;li&gt;Using the 
&lt;a href=&#34;https://chrome.google.com/webstore/detail/intention-stop-mindless-b/dladanhaondcgpahgiflodhckhoeohoe&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&amp;ldquo;Intention&amp;rdquo;&lt;/a&gt; Chrome extension by DK&lt;/li&gt;
&lt;li&gt;Keeping all notifications on my phone turned off&lt;/li&gt;
&lt;li&gt;Asking the people I live with to get my attention first before starting a conversation with me&lt;/li&gt;
&lt;li&gt;Announcing my current active goal publicly (e.g. in a chat room)&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://www.hidefeed.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;“Hide feed”&lt;/a&gt; Chrome extension, also by DK&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>Writing Another Snippet on Go Note Go</title>
      <link>https://davidbieber.com/snippets/2022-03-07-snippets-on-gng-ii/</link>
      <pubDate>Mon, 07 Mar 2022 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-03-07-snippets-on-gng-ii/</guid>
      
      <description>&lt;p&gt;After thinking through 
&lt;a href=&#34;https://davidbieber.com/snippets/2022-03-06-gng-snippets-divide/&#34;&gt;the tension between Go Note Go and snippets&lt;/a&gt; yesterday,
I now wonder if there&amp;rsquo;s a good way to write a snippet draft on Go Note Go.
I&amp;rsquo;ve done so 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-09-27-snippet-on-go-note-go/&#34;&gt;once before&lt;/a&gt;, when Go Note Go was only two weeks old, so I know it&amp;rsquo;s possible. But five months later I&amp;rsquo;ve written many snippet-worthy ideas on Go Note Go, but no additional snippets, which leads me to ask &amp;ldquo;why?&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;The first question I would need to answer is at what point during the writing of a snippet draft do I have to know that I&amp;rsquo;m writing a snippet draft. If I have to know upfront, that suggests one interface, whereas if I discover halfway into writing something that I think I&amp;rsquo;m writing a snippet draft, that suggests a different UX.&lt;/p&gt;
&lt;p&gt;If I know upfront, I can create a new session (in the Roam uploader) using shift-enter, and then I can simply type the full snippet draft. That&amp;rsquo;s what I&amp;rsquo;m doing now.&lt;/p&gt;
&lt;p&gt;If, however, I discover midway into typing something that I&amp;rsquo;m typing a snippet draft, then it may begin in the middle of a session. This isn&amp;rsquo;t such a big deal; when I clean up the draft I can remove the initial segment that isn&amp;rsquo;t meant to be part of the snippet. The start of the snippet, when I didn&amp;rsquo;t know I was writing a snippet, might be muddier than the rest, but that doesn&amp;rsquo;t stand in the way of producing snippet-quality content.&lt;/p&gt;
&lt;p&gt;In both cases, I&amp;rsquo;ll want a way to indicate that I&amp;rsquo;ve written a snippet draft so that I can find it later.
(At this point in the snippet writing I encountered a bug &amp;ndash; notes that contained quotation marks were being dropped! I&amp;rsquo;ve now 
&lt;a href=&#34;https://github.com/dbieber/GoNoteGo/pull/32&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;fixed this bug&lt;/a&gt;, and am recreating the lost content from this snippet as follows.)&lt;/p&gt;
&lt;p&gt;A simple option is to use a hashtag to indicate where a snippet draft lives. If I were working in Roam directly, I would use a two-word hashtag, &amp;ldquo;#[[Snippet draft]]&amp;rdquo;. However, this is a mouthful to type on Go Note Go, which lacks autocomplete (how do you design an autocomplete experience suitable for a headless keyboard?), since getting all that syntax exactly correct is tricky (a hash &lt;em&gt;and&lt;/em&gt; double-brackets!).&lt;/p&gt;
&lt;p&gt;If instead we adopt the hyphenated #snippet-draft then the double-brackets become unnecessary. Still simpler is the single word #draft. This seems the easiest to get right consistently if I&amp;rsquo;m going to be typing it in the dark while half asleep.&lt;/p&gt;
&lt;p&gt;So, I think I&amp;rsquo;ll adopt that convention for now, and revisit later as needed (it seems unlikely it will be needed.)&lt;/p&gt;
&lt;p&gt;#draft&lt;/p&gt;
&lt;p&gt;This system seems great for writing snippet drafts at GNG when I&amp;rsquo;m in a comfortable typing position, such as at a desk. There does seem to be something missing for when I&amp;rsquo;m drifting off to sleep though, as I often am when using GNG. I&amp;rsquo;m currently comfortably stationed at a desk, so I&amp;rsquo;ll defer thinking through the sleep-GNG-usage snippet writing scenario until after I sleep on it some.&lt;/p&gt;
&lt;p&gt;Having now completed this snippet draft, I&amp;rsquo;m going to head to a computer with a monitor in order to publish it.&lt;/p&gt;
&lt;p&gt;(Hello from the computer-with-monitor! This snippet is headed for publication now!)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The Go Note Go / Snippets Divide</title>
      <link>https://davidbieber.com/snippets/2022-03-06-gng-snippets-divide/</link>
      <pubDate>Sun, 06 Mar 2022 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-03-06-gng-snippets-divide/</guid>
      
      <description>&lt;p&gt;I love using Go Note Go. Sitting down with no screen, just a keyboard, feels really good.
It clears my head, and straightens out my thoughts. I imagine meditation feels similar to some people.&lt;/p&gt;
&lt;p&gt;In some ways, Go Note Go is fulfilling some of the early objectives of 
&lt;a href=&#34;https://davidbieber.com/snippets/&#34;&gt;snippets&lt;/a&gt;.
It allows me to &lt;em&gt;write&lt;/em&gt; without hesitation or uncertainty.
However, that was not precisely 
&lt;a href=&#34;https://davidbieber.com/snippets/2019-12-30-writing-for-no-audience/&#34;&gt;my goal with snippets&lt;/a&gt;.
My goal with snippets was to be able to &lt;em&gt;write publicly&lt;/em&gt; without hesitation or uncertainty.&lt;/p&gt;
&lt;p&gt;Coming back to write this snippet, having written so much on 
&lt;a href=&#34;https://davidbieber.com/projects/go-note-go/&#34;&gt;Go Note Go&lt;/a&gt; lately,
snippet-writing feels a little heavier than it used to.
It feels a little more like I&amp;rsquo;m writing something public, whereas for so long
snippet-writing had felt like I was writing for no audience.&lt;/p&gt;
&lt;p&gt;Fortunately, this heaviness faded quickly. Even four paragraphs into this snippet, having now spent a full minute or more reminding myself of my rules and efforts for keeping the barrier to publication low, this feels easy to write again.&lt;/p&gt;
&lt;p&gt;Still, there is a tension between Go Note Go writing and snippet writing that this minute of thinking does not resolve.
The tension is this:
I write so much in Go Note Go, including dozens of ideas that would be great to publish for snippets,
but as a result of writing them in Go Note Go, I am less inclined to make snippets of them.&lt;/p&gt;
&lt;p&gt;Why is this? Is it because I have a limited amount of snippet-quality writing time in me, and I&amp;rsquo;ve repurposed it for Go Note Go writing? Is it because writing something I&amp;rsquo;ve already written about is less enjoyable than writing something new? I think it&amp;rsquo;s a combination of these things, more the latter than the former.&lt;/p&gt;
&lt;p&gt;When I write in Go Note Go, the quality bar is &lt;em&gt;even lower&lt;/em&gt; than for snippets (hard to imagine, I know).
The Go Note Go writing is full of typos and repetitions. The typos are there because I cannot see when I&amp;rsquo;m writing; I do not go back to correct anything because there&amp;rsquo;s no mechanism for it.
Also because Go Note Go is not published anywhere, I can drop inhibitions even further than I do for snippet writing.&lt;/p&gt;
&lt;p&gt;Once I&amp;rsquo;ve put a snippet idea into Go Note Go, in principle it should be easier to turn into a snippet.
It&amp;rsquo;s just a matter of cleaning up the text from Go Note Go to make it snippet-worthy.
Snippet-worthy is a much lower bar than story-worthy.
However, cleaning up text from Go Note Go to produce a snippet doesn&amp;rsquo;t seem as rewarding as writing a snippet from scratch. Snippet-writing is like thinking; Go Note Go-cleaning is another type of activity altogether.&lt;/p&gt;
&lt;p&gt;Still, there are ideas in my Go Note Go writing that I do want to publish. So, my proposed strategy is this: I&amp;rsquo;ll write snippets about those ideas from scratch, when it feels appropriate to do so. I already review my Go Note Go notes periodically, so now when I do so I&amp;rsquo;ll keep an eye out for snippet-worthy ideas. By doing so, I think there&amp;rsquo;s a good chance some of them will turn themselves into snippets simply by virtue of being sufficiently interesting to me.&lt;/p&gt;
&lt;p&gt;The biggest such idea that comes to mind is 
&lt;a href=&#34;https://davidbieber.com/snippets/2022-07-20-keyboards-everywhere/&#34;&gt;&amp;ldquo;Keyboards, keyboards, everywhere, and not a spot to think.&amp;quot;&lt;/a&gt;
This is a blog post idea I&amp;rsquo;ve written multiple parts of in different places, but which I haven&amp;rsquo;t pulled together into its complete form yet. It&amp;rsquo;s a post about the promise of technology, how attention-seeking tech has prevented us from delivering on that promise, and how headless keyboards like Go Note Go provide a path toward reclaiming our attention and allowing us to reach out fullest potential as users of modern tech.&lt;/p&gt;
&lt;p&gt;A 
&lt;a href=&#34;https://davidbieber.com/posts/&#34;&gt;blog post&lt;/a&gt; isn&amp;rsquo;t a 
&lt;a href=&#34;https://davidbieber.com/snippets/&#34;&gt;snippet&lt;/a&gt;, but I&amp;rsquo;ve decided (after initial hesitation) that it would be totally fine to produce snippets using content that will ideally eventually make it into a blog post.
This is similar to my decision to allow myself to publish incomplete snippets.
It trades off some novelty when the blog post is finally published in return for keeping the bar to publishing snippets extraordinarily low. I value that goal more than I value preserving any kind of surprisal when I publish a blog post, rare as that is.
So, I&amp;rsquo;m likely to write about the &amp;ldquo;Keyboards, keyboards, everywhere, and not a spot to think&amp;rdquo; idea in snippets well before producing the blog post I aspire for it. (Update: 
&lt;a href=&#34;https://davidbieber.com/snippets/2022-07-20-keyboards-everywhere/&#34;&gt;Done here!&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;In writing this snippet, I trawled through some of my Go Note Go writing. It&amp;rsquo;s fun for me to look through. It&amp;rsquo;s a distraction from finishing this snippet though. I look forward to writing snippets about some of the ideas I encounter in these Go Note Go expeditions.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Go Note Go Writing Volume</title>
      <link>https://davidbieber.com/snippets/2022-02-14-go-note-go-writing-volume/</link>
      <pubDate>Mon, 14 Feb 2022 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-02-14-go-note-go-writing-volume/</guid>
      
      <description>&lt;p&gt;Lately I&amp;rsquo;ve been writing a lot, but not putting up any new snippets.
Where has all the writing gone? Into 
&lt;a href=&#34;https://davidbieber.com/projects/go-note-go&#34;&gt;Go Note Go&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It has been 150 days since I started Go Note Go.
I have written on Go Note Go on 91 of those days, producing 54,000 words.
I&amp;rsquo;ve spent a little over 24 hours total doing so, making my writing speed a bit shy of 40 wpm.&lt;/p&gt;
&lt;p&gt;I review more of my Go Note Go writing than I might expect, given its volume and that none of it has translated into published snippets.
Since 
&lt;a href=&#34;https://davidbieber.com/snippets/2022-01-08-gng-messager-snippet-plans/&#34;&gt;turning Go Note Go into an outliner&lt;/a&gt;,
the experience of reviewing my writing has been much more comfortable than it was previously.&lt;/p&gt;
&lt;p&gt;When I write in Go Note Go using the &amp;ldquo;Roam Research&amp;rdquo; uploader, my writing is divided into &amp;ldquo;sessions&amp;rdquo;.
Each session starts with a line containing only the time. The rest of the writing is nested beneath.
&lt;img src=&#34;session.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;When I review my writing in Go Note Go, I do so session by session, putting a summary of the session in that top line of the session, and then collapsing the session. Often the top line is a block-reference to one or more of the lines from the session. For example,
&lt;img src=&#34;session-collapsed.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;This compresses the 600 words I might write on a given day and presents them in a series of often 10 or fewer individual lines.&lt;/p&gt;
&lt;p&gt;While I like that I can and do review my writing to a greater degree than expected, I think there&amp;rsquo;s still substantial improvement to make in the review-and-reuse experience.
In particular, one idea I&amp;rsquo;m excited about and which I&amp;rsquo;ve been writing about in Go Note Go a fair amount, is hiring someone to review my notes and process them into a summary / a newsletter for myself.&lt;/p&gt;
&lt;p&gt;My thinking there is that I write a lot and there is definitely more in my writing than fits in my working memory at any time (this idea, that I want access to more than fits in working memory, has been recurring a fair amount lately).
By leaning on another person, I can more effectively resurface the ideas that I most want to revisit. I&amp;rsquo;m posting this snippet as is, but this idea itself is one I&amp;rsquo;m eager to revisit in the future.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Applying Lessons from Snippets to LaLTaL</title>
      <link>https://davidbieber.com/snippets/2022-01-18-snippets-lessons-for-laltal/</link>
      <pubDate>Tue, 18 Jan 2022 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-01-18-snippets-lessons-for-laltal/</guid>
      
      <description>&lt;p&gt;
&lt;a href=&#34;https://www.laltal.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;LaLTal &amp;ndash; short for &amp;ldquo;learn a little, teach a little&amp;rdquo;&lt;/a&gt;
is a novel learning app from John Cumbers
built on the extraordinary power of learning by teaching.
I tried it out tonight, and I had a great time learning a bit about blockchain and synthetic biology.
I really appreciated the opportunity to practice explaining the concepts that came up in the questions. Coming up with these explanations on the spot felt like exercising an underutilized muscle. I think I&amp;rsquo;ll be doing more of this.&lt;/p&gt;
&lt;p&gt;One thing I think could really improve the experience further though
would be if recording was decoupled from production.
The simplest way of doing this would be a &amp;ldquo;draft record&amp;rdquo; button,
and a more interesting way would be a more sophisticated but still simple audio editor, an idea I&amp;rsquo;ll detail later on in this snippet.
The core of my suggestion isn&amp;rsquo;t about the difference in &lt;em&gt;functionality&lt;/em&gt; between a potential &amp;ldquo;draft record&amp;rdquo; feature and the current &amp;ldquo;record&amp;rdquo; feature.
Instead, it&amp;rsquo;s about the mindset that the UI induces.&lt;/p&gt;
&lt;p&gt;Consider 
&lt;a href=&#34;https://davidbieber.com/snippets/&#34;&gt;snippets&lt;/a&gt;.
When I write these snippets, 
&lt;a href=&#34;https://davidbieber.com/snippets/2019-12-30-writing-for-no-audience/&#34;&gt;I write them for no audience&lt;/a&gt;.
I don&amp;rsquo;t expect to share them, or for people to read them,
and that makes them easier to write.&lt;/p&gt;
&lt;p&gt;This snippet is an exception; I fully expect to share it with a few people once it&amp;rsquo;s written. Maybe. There&amp;rsquo;s still a piece of my mind that knows that it might just be an ordinary snippet, never shared. And certainly it won&amp;rsquo;t share widely or automatically when it&amp;rsquo;s published. I can put it on my website without anyone ever seeing it, at which point deciding to share it becomes a much lighter weight action than a single decision to both &lt;em&gt;write and share it&lt;/em&gt; would have been.&lt;/p&gt;
&lt;p&gt;The lesson I&amp;rsquo;ve learned from writing snippets is that it&amp;rsquo;s easier to produce content when you&amp;rsquo;re not doing it for anyone, or with any intention to share it.
Of course, I don&amp;rsquo;t know how true this is for everyone, but I suspect that since it is true for me, it applies to some reasonably sized portion of the population.&lt;/p&gt;
&lt;p&gt;This lesson from writing snippets can be applied to LaLTaL too.
If the app put people in a mindset where they felt like they weren&amp;rsquo;t recording a final explanation to be shared,
but rather were trying on the words for size,
I think people could reach a point where they understand the material better and are more capable of sharing it.
They might even produce something they want to share even if they didn&amp;rsquo;t start the recording intending for it to be the version for sharing; I know that&amp;rsquo;s happened to me in writing snippets loads of times.&lt;/p&gt;
&lt;p&gt;Listening to other people&amp;rsquo;s explanations in the app
left me with a couple of observations &amp;ndash; possible shortcomings in people&amp;rsquo;s answers that I think setting the right mindset or environment might be able to overcome.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;People move quickly over complicated parts to keep their explanation short.&lt;/p&gt;
&lt;p&gt;I saw this multiple times in people&amp;rsquo;s explanations of blockchain-related concepts.
When people got to the part of the explanation about cryptographic hash functions,
instead of recognizing the limitation in either their explanation or their understanding, they swept it under the rug in order to keep the explanation fluid and &amp;ldquo;appropriate&amp;rdquo; in length. I think the current record-once setup leaves people averse to grappling with complexity.&lt;/p&gt;
&lt;p&gt;If people felt like a long pause to think right in the middle of their explanation were OK, they maybe they wouldn&amp;rsquo;t exhibit this sweeping-under-the-rug behavior.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;People speak slowly to buy themselves time to think, rather than pausing to think or thinking ahead of time.&lt;/p&gt;
&lt;p&gt;It reminds me a bit of 
&lt;a href=&#34;https://www.youtube.com/watch?v=0cA9j2EpAHE&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Charlie Brown&amp;rsquo;s &amp;ldquo;The Book Report&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The name of the book about which,
this book report is about is,
Peter Rabbit which is about this&amp;hellip;
Rabbit.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now, as someone answering the questions, there&amp;rsquo;s nothing wrong with this!
It&amp;rsquo;s a great way to feel your way toward a good answer. During the slow explanation, your brain is hard at work piecing together what you&amp;rsquo;ll say next.
Still, I think it&amp;rsquo;s important to recognize that this is happening and that there might be a UX that leads to a better experience for both answerer and listener.&lt;/p&gt;
&lt;p&gt;If people felt like they could record in multiple pieces, pause as long as they like to think, and throw out individual pieces,
perhaps they would produce even better explanations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;People trail off with uncertainty and apprehension&lt;/p&gt;
&lt;p&gt;This happened in several of the explanations I listened to.
The speaker is explaining something, it&amp;rsquo;s going well, and then they realize they&amp;rsquo;re either about to repeat themself or have nothing more to add.
So, they trail off, their voice weakens a little, and they remark that they&amp;rsquo;re done.&lt;/p&gt;
&lt;p&gt;If instead people were recording for themselves,
hearing themselves think through the various aspects of their answer,
and then at the end piecing together the parts of their own musings that they like,
it would avoid these tenuous endings.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;All of this leads me to brainstorm possible user interface ideas.
Know that the purpose of this snippet is not to advocate for any single idea,
but rather simply to share my thinking.
My aim is for these ideas to inspire further ones, not for these ideas to win out.&lt;/p&gt;
&lt;h5 id=&#34;version-1-multiple-recordings&#34;&gt;Version 1: Multiple recordings&lt;/h5&gt;
&lt;p&gt;(This is simpler to implement, but I imagine less effective, than Version 2.)
The idea here is you can record multiple recordings &amp;ndash; as many as you like &amp;ndash; and then you can rearrange them or delete them.
With this UX, already an answerer can comfortably pause their recording if they feel they&amp;rsquo;ve reached a part of the explanation that their stumbling over. They can gather their thoughts, then proceed.&lt;/p&gt;
&lt;h5 id=&#34;version-2-a-single-multi-piece-recording&#34;&gt;Version 2: A single multi-piece recording.&lt;/h5&gt;
&lt;p&gt;(This UX could be simpler for the user, but is more technically ambitious.)
When you start recording,
the screen begins filling up with your recording.
Each time you pause speaking for more than two seconds,
a boundary appears in your recording.
The boundaries effectively divide time into distinct clips.
Silence is stripped from the beginning and end of each clip automatically.
As in Version 1 of the idea, the answerer has the opportunity to rearrange or delete clips by tapping and dragging them.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;There&amp;rsquo;s a tension between these UX ideas and another important aspect of getting people to publish, that must be carefully balanced.
If people have opportunities to critique their own work, and polish it, they may be reluctant to publish because the mental quality bar they set for themselves could be too high.
This has been another critical lesson from snippets &amp;ndash; making the quality bar to publication as low as possible has been essential for me feeling comfortable writing and publishing my snippets.
Editing tools push the quality bar higher, and so the UX ideas I present above might have opposite the desired effect.&lt;/p&gt;
&lt;p&gt;With this in mind, I present a third version of the UX, one that balances the desire to let people pause and think with the goal of keeping people feeling comfortable publishing rather than falling into a perfection-trap.&lt;/p&gt;
&lt;hr&gt;
&lt;h5 id=&#34;version-3-one-recording-with-a-pause-feature&#34;&gt;Version 3: One recording with a &amp;ldquo;Pause&amp;rdquo; feature&lt;/h5&gt;
&lt;p&gt;In this final variant of the idea, the user pushes to record,
but they can pause and resume their recording at any time.
Simply by letting people pause, perhaps we can give people the freedom to think before they speak when they encounter a tough concept unexpectedly during their explanation.
At the same time, this keeps the recording UX simple, so hopefully it avoids the potential pitfall of having people avoid clicking submit because they have reached the perfect recording yet.&lt;/p&gt;
&lt;p&gt;Hopefully the result is explanations that are both cogent, fun to produce, and plentiful.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Pursuing your dreams</title>
      <link>https://davidbieber.com/snippets/2022-01-11-pursuing-your-dreams/</link>
      <pubDate>Tue, 11 Jan 2022 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-01-11-pursuing-your-dreams/</guid>
      
      <description>&lt;p&gt;
&lt;a href=&#34;https://davidbieber.com/snippets/2020-01-02-pyd-swyt-cf-bh-din/&#34;&gt;pyd-swyt; cf-bh-din&lt;/a&gt;. Today, we focus on pyd. Or maybe bh.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Musings on pursuing your dreams.&lt;/strong&gt;
Pursuing your dreams is easier when you know what they are.
Figuring out your dreams is part of pursuing them.
All of this is of course made more practical when you have the financial and personal flexibility to prioritize your dreams.&lt;/p&gt;
&lt;p&gt;What are my dreams?&lt;br/&gt;
Here, I think of my dreams as epitomized versions of the things I enjoy.&lt;/p&gt;
&lt;p&gt;I enjoy building fun side-projects, little things that scratch my own itch.&lt;br/&gt;
I enjoy sharing them with other people, and feeling other people appreciate them too.&lt;br/&gt;
I enjoy collaborating on these projects with others.&lt;br/&gt;
I enjoy the feeling of progress, that barriers are falling &amp;ndash; resisting first, then falling.&lt;br/&gt;
I enjoy solving puzzles and math problems and learning new things.&lt;br/&gt;
I enjoy teaching. I enjoy spending time with family and friends.&lt;br/&gt;
I enjoy playing table tennis, and skiing, and hiking, and other outdoor activities with crisp fresh air.&lt;br/&gt;
I enjoy the fall.&lt;br/&gt;
I enjoy running on the beach in the warm salty air for miles.&lt;br/&gt;
I enjoy feeling physically fit.&lt;br/&gt;
I enjoy getting to know someone.&lt;br/&gt;
I enjoy a cool glass of water.&lt;br/&gt;
I enjoy a waterfall, buried in a forest.&lt;br/&gt;
I enjoy visiting places a second time.&lt;br/&gt;
I enjoy when my mental map of a place clicks together, and two regions become one.&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;These days I enjoy virtual reality, but maybe it&amp;rsquo;s novel technology and the feelings of empowerment and possibility that it brings that are the real draw there.
These days I enjoy note-taking, which I think might be the same.&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;I enjoy programming, and that brings those last two into some focus.&lt;br/&gt;
I enjoy organizing. Code@Nights. Tech Days. Peer Learning Groups. Study groups.&lt;br/&gt;
I enjoy online education.&lt;br/&gt;
I enjoy stories.&lt;br/&gt;
To my surprise and delight, I enjoy City Council meetings.&lt;br/&gt;
I enjoy yummy foods with powerful flavors.&lt;br/&gt;
I enjoy writing snippets.&lt;br/&gt;
I enjoy puzzle games.&lt;br/&gt;
I enjoy games that require quick reactions and physical activity.&lt;br/&gt;
I enjoy tennis and other racket sports.&lt;br/&gt;
I enjoy visiting California, and Austin, and Montreal.&lt;br/&gt;
I enjoy visiting my family in Niskayuna.&lt;br/&gt;
I enjoy being appreciated.&lt;br/&gt;
I enjoy when people enjoy my work.&lt;br/&gt;
I enjoy being helpful.&lt;br/&gt;
I enjoy reconnecting with old friends.&lt;br/&gt;
I enjoy taking silly ideas seriously.&lt;br/&gt;
I enjoy remembering, even when it&amp;rsquo;s hard.&lt;br/&gt;
I enjoy pushing myself, also when it&amp;rsquo;s hard.&lt;br/&gt;
I enjoy simplifying things, using automation and the like to reduce cognitive friction.&lt;br/&gt;
I enjoy mental clarity.&lt;br/&gt;
I enjoy a good laugh.&lt;br/&gt;
I enjoy a bad pun.&lt;br/&gt;
I enjoy being impressed, and impressing others.&lt;br/&gt;
I enjoy knowing that I&amp;rsquo;m thought of. I enjoy receiving mail.&lt;br/&gt;
I enjoy escape rooms, and cooking, and the feeling of being clean.&lt;br/&gt;
I enjoy dancing fast, and reading slow, and being well rested in the morning.&lt;br/&gt;
I enjoy spreadsheets.&lt;br/&gt;
I enjoy making Bieber Bot feel personal.&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Are these my dreams? Is my dream an environment where I can do these things as I grow up and grow old?&lt;/p&gt;
&lt;p&gt;Each of these things lasts but a moment, or a day or two at most.
Only a few items like &amp;ldquo;organizing&amp;rdquo; and &amp;ldquo;getting to know someone&amp;rdquo; from this list really extend beyond these short time frames.&lt;/p&gt;
&lt;p&gt;Are dreams bigger than this?
Not in this snippet, no.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Two Snippets I want to write about GNG and Messager</title>
      <link>https://davidbieber.com/snippets/2022-01-08-gng-messager-snippet-plans/</link>
      <pubDate>Sat, 08 Jan 2022 02:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-01-08-gng-messager-snippet-plans/</guid>
      
      <description>&lt;p&gt;I have two new ideas for snippets I want to write. They&amp;rsquo;re about Go Note Go and Messager Queue, both side projects I&amp;rsquo;ve been putting a bunch of time into the last few days. The snippet ideas are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Using Go Note Go as an outliner&lt;/li&gt;
&lt;li&gt;Adding Hacker News to Messager Queue, and then auto-queuing Twitter and HN posts for snippets.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first is about &lt;em&gt;using Go Note Go as an outliner&lt;/em&gt;. This is a new feature I&amp;rsquo;ve added to Go Note Go just in the last day or so. Before yesterday, each note entered via Go Note Go was it&amp;rsquo;s own bullet in your note-taking system. Now (at least for Roam), you can also use tab to indent and dedent notes.
This sounds simple, but thinking through the user experience, taking into consideration that there is no screen, was a fun experience.
It also sounds like an only marginal improvement, but for me it&amp;rsquo;s been rewarding more than I expected. It has interesting interactions with the 
&lt;a href=&#34;https://davidbieber.com/post/2022-01-08-new-messager-setup/&#34;&gt;new message sending feature&lt;/a&gt; &amp;ndash; making sending messages even more enjoyable.
And it lends itself well to progressive summarization and chronologically organized notes;
with the current implementation, each note-taking &amp;ldquo;session&amp;rdquo; has a timestamp and blank space for a summary at the top of the session. I can fill in the blank space and then collapse the notes, making it easier to skim through them later.
Perhaps these summaries will serve as training / fine-tuning data for an autosummarizer later.&lt;/p&gt;
&lt;p&gt;The second snippet idea is a new script I am thinking of writing that will add messages to my new Messager Queue automatically.
I&amp;rsquo;ve toyed with the idea of sharing more of my snippets publicly in the past.
Currently, I only share them very rarely.
Only partially is this an active decision; it is also partially inertia and there being an activation energy and unnaturalness for me in posting publicly.
While the active decision reasons will remain, having auto-generated messages populate my Messager Queue periodically will really dilute any inertia / activation energy / unnaturalness reasons for not sharing snippets, and those are precisely the reasons I want to eliminate.
Doing this will require a small change to the Messager Queue to support Hacker News; this should only take a few minutes, as HN is already supported by Messager.
Then, it will likely take a few hours to write a script that periodically adds messages about my snippets to my Messager Queue.
One source of these messages will be the &amp;ldquo;message&amp;rdquo; field at the top of some of my snippet frontmatters.
For others I can just make a templated message using the snippet title; the beauty of Messager Queue is I don&amp;rsquo;t need to autogenerate the perfect message, since I can tweak or rewrite it before approving the message to go out.&lt;/p&gt;
&lt;p&gt;So, I&amp;rsquo;ve now put down all the things I wanted to say about those two snippets. Does it still make sense to write them? I don&amp;rsquo;t know; I might turn them into new snippets anyway.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>I made a new Post, but why?</title>
      <link>https://davidbieber.com/snippets/2022-01-08-new-post-why/</link>
      <pubDate>Sat, 08 Jan 2022 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-01-08-new-post-why/</guid>
      
      <description>&lt;p&gt;The last two years I&amp;rsquo;ve mostly been writing snippets, but today I wrote 
&lt;a href=&#34;https://davidbieber.com/post/2022-01-08-new-messager-setup&#34;&gt;a new post&lt;/a&gt;. Why?&lt;/p&gt;
&lt;p&gt;I initially wrote it as a snippet.
And the total time it took to write was short, like a snippet, not long like a typical post.
So there are reasons to think it is not unlike other snippets.&lt;/p&gt;
&lt;p&gt;The reason I chose to publish it as a post rather than as a snippet is it seemed more significant.
The last few days, playing with all the progress I&amp;rsquo;ve made in Go Note Go and Messager, left me wanting to share my work with other people. So, by publishing it as a post, it will be more prominent on my website, and over time more people will see it.&lt;/p&gt;
&lt;p&gt;Another small reason is I hadn&amp;rsquo;t made a post in a long time. By converting this snippet into a post, I maintain a pattern of periodic posting of posts. When someone (likely me) looks at the list of post dates, there won&amp;rsquo;t be a large gap, even if I don&amp;rsquo;t write another post for a year.
So, I suppose I wanted to remove any internal pressure for writing posts that may have been building up.
At first I thought that describing this reason, I would end by noting that it&amp;rsquo;s a shallow reason;
after all, the appearance of consistent posting feels like a shallow thing to me.
Now that I&amp;rsquo;ve written it out though, I realize it&amp;rsquo;s more about managing the expectations set by a small shallow piece of me, not just about conceding to that piece.
It is, in part, me conceding to that piece though.&lt;/p&gt;
&lt;p&gt;Finally &amp;ndash; last reason &amp;ndash; it had the right heft and length to feel OK as a post.&lt;/p&gt;
&lt;p&gt;Cheers.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Efficient Minds Fallacy</title>
      <link>https://davidbieber.com/snippets/2022-01-07-efficient-minds-fallacy/</link>
      <pubDate>Fri, 07 Jan 2022 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-01-07-efficient-minds-fallacy/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;This snippet is similar to these related snippets from March 2021: 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-03-04-the-efficient-minds-hypothesis/&#34;&gt;#1&lt;/a&gt; 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-03-10-efficient-minds-hypothesis-failing&#34;&gt;#2&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been thinking about the Efficient Minds Fallacy lately, and so I read this as it relates to the EMF.&lt;/p&gt;
&lt;p&gt;The Efficient Minds Fallacy occurs when someone incorrectly believes in the 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-03-10-efficient-minds-hypothesis-failing&#34;&gt;Efficient Minds Hypothesis&lt;/a&gt; or one of it&amp;rsquo;s consequences. The Efficient Minds Hypothesis is only slightly more silly than it&amp;rsquo;s namesake, the Efficient Market Hypothesis.&lt;/p&gt;
&lt;p&gt;The Efficient &lt;strong&gt;Minds&lt;/strong&gt; Hypothesis (EMH) says that if you know $A$ and you know $A \rightarrow B$, then you also know $B$. On the surface this sounds reasonable, but it is demonstrably false and has pernicious consequences if believed.&lt;/p&gt;
&lt;p&gt;To put it in plain English: the EMH states that given the information available to you, you know all the conclusions that can be deduced from that information.&lt;/p&gt;
&lt;p&gt;This is obviously false. If it were true, you would never lose a game of chess (no new information is introduced).&lt;/p&gt;
&lt;p&gt;Main reasons it&amp;rsquo;s false:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Noticing that a reasoning step can take place requires attending to the premises; your attention may be on other information, and so you might not notice that a reasoning step can be performed.&lt;/li&gt;
&lt;li&gt;Computation takes time. Even if you are acutely aware of two premises, it still requires time to perform the step of reasoning to reach the conlusion.&lt;/li&gt;
&lt;li&gt;Attending to the premises takes time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-03-04-the-efficient-minds-hypothesis/&#34;&gt;why do people believe it&lt;/a&gt;? And what evidence do we have that people believe it?&lt;/p&gt;
&lt;p&gt;My estimation is: it largely manifests in over confidence, allocating insufficient time for thinking deeply about things, insufficient time for thinking deeply (not about things in particular), and under-reliance on others / an under-appreciation for the power of a second brain or second perspective (e.g. not seeking advice as much)&lt;/p&gt;
&lt;p&gt;I know I&amp;rsquo;ve observed these things in myself. Almost always when I do ask for someone else&amp;rsquo;s advice or perspective on something (something I&amp;rsquo;d like to do more of), I am surprised and delighted by the insight they are able to offer. I attribute the surprisal that I experience to my natural inclination toward believing the EMH.&lt;/p&gt;
&lt;p&gt;I want to clarify: at a logical level, I do absolutely do not believe the EMH; I think it&amp;rsquo;s preposterous and demonstrably false. Nevertheless, when I am not attending to the EMH, and am instead attending to some other problem, I forget that I have concluded the EMH is false, and so I am still liable to the EMF. So I find it useful to remind myself of the EMF periodically so that it feels more natural seeking other people&amp;rsquo;s advice, seeking collaborations, acknowledging that I may have missed many things when considering a problem.&lt;/p&gt;
&lt;p&gt;So, what are the implications of EMF for meditation?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Letting your brain do some work is good, because good thinking takes time.&lt;/li&gt;
&lt;li&gt;Whatever conclusions you&amp;rsquo;ve reached about meditation and mindfulness so far are not necessarily the final conclusions you will reach, even if you don&amp;rsquo;t learn anything new about the practices.&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>Go Note Go Messager without Pixel-Space Automation</title>
      <link>https://davidbieber.com/snippets/2022-01-02-pixel-space-automation/</link>
      <pubDate>Sun, 02 Jan 2022 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2022-01-02-pixel-space-automation/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;This snippet was originally going to be about pixel-space automation. Then I found I didn&amp;rsquo;t need it for what I wanted to do: sending messages to Twitter, Facebook, Slack, and Discord from Go Note Go, Roam Research, and Bieber Bot.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Happy New Year! I&amp;rsquo;d really like to automate Mac apps that don&amp;rsquo;t expose actions to Automator
using pixel-space navigation and clicks and typing to control the automation. This is why and how.&lt;/p&gt;
&lt;p&gt;(Update from the end of the snippet: By the time I finished writing the snippet, I had automated everything I intended to using browser automation in Browserflow, never once needing to automate Ferdi. I still think pixel-space automation would be wonderful, but my initial motivation for it turns out to be insufficient.)&lt;/p&gt;
&lt;h3 id=&#34;motivation-improving-messager-by-automating-ferdi&#34;&gt;Motivation: Improving Messager by Automating Ferdi&lt;/h3&gt;
&lt;p&gt;I have a side project &amp;ldquo;Messager&amp;rdquo; that allows for programmatically sending and receiving messages
across a wide variety of messaging services.
I also use Ferdi for manually managing an even wider variety of messaging services.&lt;/p&gt;
&lt;p&gt;Currently Messager supports
Facebook Messenger (as myself and as Bieber Bot),
Twitter (public tweets, private tweets, and DMs),
HackerNews,
and it has limited support for Slack and Discord.
Ferdi, on the other hand, supports a much wider range of services, but doesn&amp;rsquo;t offer programmatic access;
I use Ferdi with
Facebook Messenger (as myself and as Bieber Bot),
Twitter (public tweets, private tweets, and DMs),
multiple Slacks,
Discord,
Gitter,
WhatsApp,
Telegram,
as well as for non-messaging services like Roam Research,
multiple spreadsheets,
supervisord,
and other adhoc use cases.&lt;/p&gt;
&lt;p&gt;I would like to extend Messager to have wider support,
particularly to improve support for Slack and Discord.
To do this, &lt;mark&gt;I&amp;rsquo;d love to automate Ferdi&lt;/mark&gt;.&lt;/p&gt;
&lt;h3 id=&#34;motivation-go-note-go---messager-bridge&#34;&gt;Motivation: Go Note Go - Messager Bridge&lt;/h3&gt;
&lt;p&gt;Why do I want to improve Messager &lt;em&gt;now&lt;/em&gt;? It&amp;rsquo;s because of 
&lt;a href=&#34;https://davidbieber.com/projects/go-note-go&#34;&gt;Go Note Go&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m adding messaging support to Go Note Go. The main use case I&amp;rsquo;m targeting is this:&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m drifting off to sleep and realize I want to tell someone something.
So I write in Go Note Go something along the lines of &amp;ldquo;Tell John Smith Hey John, I have this new idea for Go Note Go where you can send messages as your drifting off to sleep &amp;ndash; maybe I can tell you about it tomorrow&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;When I wake up the following morning, Bieber Bot has messaged me with a link to a spreadsheet.
It has all the messages I drafted the previous night (they haven&amp;rsquo;t been sent yet).
There, I can clean them up for any typos and &amp;ldquo;approve&amp;rdquo; them (mark them as OK to send).
And once they&amp;rsquo;re approved, they&amp;rsquo;ll be sent automatically using Messager.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s in support of this project that I&amp;rsquo;d love for Messager to support a wider variety of services.
Ideally the system will intelligently select the service to use to send the message based on the recipients.
It will include the service in the spreadsheet, so that I can adjust the service if needed before approving the message.&lt;/p&gt;
&lt;p&gt;So this is going to be a Go_Note_Go-Sheets-Messager-Bieber_Bot collab.&lt;/p&gt;
&lt;p&gt;tl;dr Go Note Go adds draft messages to a spreadsheet. Bieber Bot uses that spreadsheet to message me about new draft messages, and to message friends on my behalf with approved messages.&lt;/p&gt;
&lt;h3 id=&#34;motivation-going-beyond&#34;&gt;Motivation: Going beyond&lt;/h3&gt;
&lt;p&gt;For the Messager application described so far, pixel-space automation is not necessary.
All of the services I want to automate can be opened in the Browser,
and so existing Browser automation techniques are sufficient.
I would use Browserflow for this if it supported programmatic triggers, but it does not.
(Psst&amp;hellip; DK, can you add the ability to programmatically trigger a local flow please?)&lt;/p&gt;
&lt;p&gt;Given this, why is pixel-space automation interesting?
It&amp;rsquo;s because it would enable
(1) easier automation construction for the automations I&amp;rsquo;m interested in
and (2) it enables a much larger class of automations, and empowerment is key.

&lt;a href=&#34;https://davidbieber.com/snippets/2021-12-07-future-automation-software/&#34;&gt;See here for my dreams for the future of automation.&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;ferdi-actions&#34;&gt;Ferdi Actions&lt;/h3&gt;
&lt;p&gt;The main actions I want for the Messager application are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ferdi: Navigating to different services&lt;/li&gt;
&lt;li&gt;Discord: Choosing a server, channel, or recipient&lt;/li&gt;
&lt;li&gt;Discord: Sending and receiving messages on that channel&lt;/li&gt;
&lt;li&gt;Slack: Choosing a channel or recipient&lt;/li&gt;
&lt;li&gt;Slack: Sending and receiving messages on that channel&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;the-challenge&#34;&gt;The Challenge&lt;/h3&gt;
&lt;h5 id=&#34;why-are-the-discord-and-slack-apis-not-sufficient&#34;&gt;Why are the Discord and Slack APIs not sufficient?&lt;/h5&gt;
&lt;p&gt;Both Discord and Slack have policies against using self-bots. Their APIs don&amp;rsquo;t allow you to programmatically control your own user account. So, controlling your account as a human would, through the provided chat client, is a natural way to approach the problem.&lt;/p&gt;
&lt;p&gt;The advantages of using Ferdi over the browser are: (1) it uses service hibernation, so you can skip loading the pages and logging in each time you start using a website, (2) maybe you can keep using the browser while Ferdi automates in the background.&lt;/p&gt;
&lt;p&gt;Each of these actions is doable using existing browser automation tools. Navigating to different services in the browser requires authentication though, if you&amp;rsquo;re not already logged in (which I would be in Ferdi). Perhaps with Browserflow&amp;rsquo;s cookie sharing feature, I can also already be logged in at the start of a Browserflow flow even on Cloud.&lt;/p&gt;
&lt;h3 id=&#34;current-status&#34;&gt;Current Status&lt;/h3&gt;
&lt;p&gt;I took a break in the middle of writing this flow and now I&amp;rsquo;ve implemented sending messages via Browserflow in both Slack and Discord.
I&amp;rsquo;ve also gone further toward the Go Note Go-Messager bridge,
implementing a few of the other steps.
Whenever I use &amp;ldquo;@Person&amp;rdquo; in Roam, Bieber Bot automatically copies the message into a spreadsheet.
The spreadsheet has an &amp;ldquo;Approval&amp;rdquo; column, where I can mark messages as OK to send.
Bieber Bot will then use Messager to send any approved messages.
Since Go Note Go sends it&amp;rsquo;s notes to Roam, this completes the circuit.&lt;/p&gt;
&lt;p&gt;I can now send messages from Go Note Go to any of Facebook Messenger, Twitter, Slack, and Discord.
I&amp;rsquo;m still excited about pixel-space automation, but I&amp;rsquo;ll have to save that excitement for a future snippet; for now, Browserflow was sufficient.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Brainstorming How to Replicate AIM Statuses Today</title>
      <link>https://davidbieber.com/snippets/2021-12-21-aim-statuses/</link>
      <pubDate>Tue, 21 Dec 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-12-21-aim-statuses/</guid>
      
      <description>&lt;p&gt;How do we bring back reliable aim statuses?&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like for folks to know if someone is genuinely available for a conversation.&lt;/p&gt;
&lt;p&gt;Some options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Could just ask.&lt;/li&gt;
&lt;li&gt;Could post statuses on social media.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Neither of these really appeal to me. They feel kind of heavyweight. I guess, of the two, the former is more appealing. The latter would require rewriting social conventions a bit too much.&lt;/p&gt;
&lt;p&gt;Maybe if the &amp;ldquo;asking&amp;rdquo; felt automated, like if there was a pre-written canned message (that explained that it was a canned message), it could feel more lightweight. For example:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Hi, David Bieber would like to know if you&amp;rsquo;re available for a conversation now-ish. It&amp;rsquo;s not urgent. No need to respond if you&amp;rsquo;re not available. If you are available, Hi! Otherwise, you can just ignore this. -Bieber Bot&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Signing it Bieber Bot is supposed to indicate it&amp;rsquo;s a pre-written message, but I&amp;rsquo;m not sure if that comes across. Maybe adding &amp;ldquo;(This is a pre-written message.)&amp;rdquo; would be safer.&lt;/p&gt;
&lt;p&gt;Later, when people see that message for the second/third/nth time, they won&amp;rsquo;t have to read the whole thing, just seeing the general shape of it will be enough.&lt;/p&gt;
&lt;p&gt;But it will still contain it&amp;rsquo;s full meaning.&lt;/p&gt;
&lt;p&gt;I guess that&amp;rsquo;s similar in spirit to the 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-01-29-kangaroo-auto-responder/&#34;&gt;kangaroo 🦘&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Sending the message for the first time though, still would feel heavy. Only the nth time would feel light.
This seems surmountable though. Maybe I&amp;rsquo;ll give it a try.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Amazon Cloud Kitchen</title>
      <link>https://davidbieber.com/snippets/2021-12-20-amazon-cloud-kitchen/</link>
      <pubDate>Mon, 20 Dec 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-12-20-amazon-cloud-kitchen/</guid>
      
      <description>&lt;p&gt;This snippet is about a fake future service that Amazon could offer one day called Amazon Cloud Kitchen. It&amp;rsquo;s the food analog of Amazon&amp;rsquo;s existing (real) Amazon Cloud Services offerings.&lt;/p&gt;
&lt;p&gt;The core idea with Amazon Cloud Kitchen is that users can submit recipes programmatically to the Cloud Kitchen, where a nearby warehouse of robotic chefs will automatically prepare the recipe. Once prepared it will be delivered in less than two hours, still warm, to your residence or restaurant.&lt;/p&gt;
&lt;p&gt;When you picture robotic chefs, you may be imagining a metallic biped with a chef&amp;rsquo;s hat. That&amp;rsquo;s not what&amp;rsquo;s is happening behind the scenes in Amazon&amp;rsquo;s Cloud Kitchen.
Instead, a series of highly modular rectangular units on rails
are performing a carefully orchestrated and optimized series of cooking tasks to prepare tens of thousands of recipes concurrently.&lt;/p&gt;
&lt;p&gt;Each recipe declaratively defines what ingredients and instruments are needed, and how they are combined.
Interchangeable robotic ovens, whisks, blenders, food dispensers, and arms zoom around the warehouse on rails completing the recipes, packaging the results, and sending them to shipping.&lt;/p&gt;
&lt;p&gt;As with Amazon&amp;rsquo;s other &amp;ldquo;Elastic&amp;rdquo; Cloud products, Amazon Cloud Kitchen scales whether you&amp;rsquo;re making a single cupcake or food to feed a football stadium. Of course, the per-unit costs decrease as the amount of food you&amp;rsquo;re submitting for preparation increases, same as it does when reserving compute units in AWS.&lt;/p&gt;
&lt;p&gt;The true beauty of Amazon Cloud Kitchen is the versatility it offers. Any recipe can be submitted, no matter how complicated the steps, no matter what the ingredients; it doesn&amp;rsquo;t matter if it&amp;rsquo;s a recipe that&amp;rsquo;s never been made before, that you couldn&amp;rsquo;t possibly buy prepared from a store. Since Amazon Cloud Kitchen uses automation to follow your recipe step-by-step, you can make recipes that suit precisely your needs.&lt;/p&gt;
&lt;p&gt;This means it can respect your dietary needs.
Let&amp;rsquo;s say you find a cake recipe on GitHub, complete with the g-code for applying the frosting pattern at the end, but it uses regular flour, whereas you want gluten-free flour.
Simply change the recipe and submit; no trouble.&lt;/p&gt;
&lt;p&gt;At a low level, recipes are expressed as source code.
The programming language allows mixing declarative constructs (&amp;ldquo;X is Y mixed with Z&amp;rdquo;) and procedural ones (&amp;ldquo;do X, then do Y&amp;rdquo; / &amp;ldquo;when X occurs, do Y&amp;rdquo;).
For inspiration for language design we can look at 
&lt;a href=&#34;https://github.com/MichaelBarney/cook&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Cook&lt;/a&gt;, but I think we can do better (an idea for a future snippet).
At a higher level, I don&amp;rsquo;t think it&amp;rsquo;s too much to ask to automatically translate human-friendly recipes into computer friendly ones. This is a challenging task, but possible with today&amp;rsquo;s technology.&lt;/p&gt;
&lt;p&gt;One of the benefits Amazon Cloud Kitchen gets from
its scale is the ability to forecast resource requirements. By looking at usage patterns, Amazon can ensure that each warehouse is stocked with adequate ingredients to meet the demand of the incoming programmatic recipes.&lt;/p&gt;
&lt;p&gt;Amazon can further provide accurate just-in-time price and timing estimates. If a warehouse is out of an ingredient and someone tries to submit a recipe that requires that ingredient,
the user can receive a confirmation notice indicating that the ingredient is on delay, and that the recipe would not be processed until some later period.&lt;/p&gt;
&lt;p&gt;For some users this is not a problem; if you&amp;rsquo;re catering a large event, you&amp;rsquo;ll likely place your order well in advance anyway. Of course, you can specify the delivery time in the future; you&amp;rsquo;re not limited to just-in-time orders.
Recurring and scheduled orders further allow Amazon to ensure the warehouses are stocked at the appropriate times to meet the demand.&lt;/p&gt;
&lt;p&gt;One challenge is dealing with allergies and food restrictions, such as avoiding nuts and keeping kosher. In order to service users with such restrictions, Amazon needs to
ensure the modular cooking components are properly cleaned and separated as appropriate. This seems well within the scope of designing the Cloud Kitchen warehouse.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s consider some example modules that would exist in the Cloud Kitchen, starting with the oven.
Recipes require baking at temperatures ranging from at least as low as 350°F to at least as high as 450°F.
Throughout the day as different recipes come in, the number of units of food requiring each different temperature will vary.
So, a possible module design for a Cloud Kitchen oven would be a long oven, 350°F at one end, and 450°F at the other end.
In between would be regions at the intervening temperatures.
As more or less space at different temperatures is needed,
different regions in the oven can be set to different temperatures.
We can view this as shifting the temperature change points left and right along the oven.
The advantage of this design is we minimize the amount of temperature changes (pre-heating and cooling) needed, allowing for faster completion of the recipes without wasting energy leaving the oven unused for any length of time.&lt;/p&gt;
&lt;p&gt;Note that this implementation of baking means that &amp;ldquo;preheat&amp;rdquo; instructions typically found in recipes do not literally translate to a &amp;ldquo;preheat&amp;rdquo; action taking place in the Cloud Kitchen. This doesn&amp;rsquo;t mean the recipe needs to be modified though; existing recipes found around the internet should work with Cloud Kitchen just fine. The recipe compiler that translates the recipe into specific instructions for the Cloud Kitchen will simply have to realize that a preheat instruction for an oven indicates that a heated oven is needed in the next step, not that the recipe requires starting with a non-preheated oven.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s consider next another critical component of the Cloud Kitchen: food storage. During the preparation of a recipe, the intermediate ingredients need to be kept in containers.
The containers of food will need to be combined, shaken, stirred, boiled, heated, cooled, chopped, smashed, strained, kneaded, folded, diced, blended, etc.
Importantly, the food storage units should be standardized and compatible with all of the food processing units they will be needed with.&lt;/p&gt;
&lt;p&gt;When a recipe is compiled (when it is converted from source code to a series of precise steps to be executed by the Cloud Kitchen), all of the requirements for the containers will be computed ahead of time. A suitable container will then be selected. This container will be of the appropriate size to hold all the ingredients that will eventually be added, and it will be compatible with all the other implements it will be used with (e.g. blending-compatible, freezing compatible, etc).&lt;/p&gt;
&lt;p&gt;The next step is to build the &amp;ldquo;Cloud Kitchen simulator&amp;rdquo; as an interesting environment in which to explore optimization techniques, and to design the Cloud Kitchen before actually getting funding and starting to build it.
When setting up the simulator, we can define the layout of the warehouse, define where ingredients will be housed, what kinds of modules are available, how reliable they are, what distribution of recipes will be coming in, etc.
We could even simulate fires and maintenance and other adverse events to ensure we&amp;rsquo;ve truly thought through everything and that the Kitchen is ready to scale.&lt;/p&gt;
&lt;p&gt;As more data about Cloud Kitchen usage comes in, and as innovation in modular components progresses, Amazon can regularly improve the layout and management of the Cloud Kitchen, reducing prices over time.
Optimizing the arrangement of ingredient stores, immovable modules (e.g. fixed ovens, refrigeration, etc), and rails for movable modules seems like an exciting and interesting challenge for the next generation to tackle.&lt;/p&gt;
&lt;p&gt;I would love to see Amazon introduce their first Cloud Kitchen in the middle of a city, an uncommon choice for a warehouse. By putting a Cloud Kitchen in a city center,
there could be a pickup option, not just delivery.
Residents could have their perfect customized lunch ready for them when they&amp;rsquo;re ready for it.&lt;/p&gt;
&lt;p&gt;Not into the Amazon Cloud Kitchen idea?
Consider instead a nice case of 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-12-09-amazon-beans/&#34;&gt;Amazon Beans&lt;/a&gt;.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;A related language feature for the recipe programming language:
implicit variables. In recipes, there is usually only ever a single object of a given type (e.g. recipes rarely use two ovens). Sometimes there are multiple objects of the same type (e.g. two bowls of ingredients). If a recipe refers to an object by its type, it doesn&amp;rsquo;t need to have any additional identifying information about that object, unless there is ambiguity. So, when you make a statement about an oven in a recipe, it&amp;rsquo;s implied that your recipe now requires an oven. Future references to an oven imply the same oven; if you want to talk about a distinct oven, you can name them or indicate which oven you&amp;rsquo;re talking about by specifying additional detail (&amp;ldquo;the 400°F oven&amp;rdquo; and &amp;ldquo;the 350°F oven&amp;rdquo;). In a future snippet we can sketch out what the language would look like, including writing the programs for a handful of example recipes. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>We Could Use Augmented Reality to Simulate Prosopagnosia</title>
      <link>https://davidbieber.com/snippets/2021-12-12-prosopagnosia-augmented-reality/</link>
      <pubDate>Sun, 12 Dec 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-12-12-prosopagnosia-augmented-reality/</guid>
      
      <description>&lt;p&gt;I was watching 
&lt;a href=&#34;https://www.youtube.com/watch?v=vFZY--lgmHs&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Lecture 4 of Nancy Kanwisher&amp;rsquo;s class &amp;ldquo;The Human Brain&amp;rdquo;&lt;/a&gt;,
and it occurred to me that we could use augmented reality to simulate prosopagnosia.
Prosopagnosia, for those unfamiliar with the term, is &amp;ldquo;face blindness&amp;rdquo;.
It affects about 2% of the population with varying degrees of severity,
and those with prosopagnosia cannot recognize faces.&lt;/p&gt;
&lt;p&gt;In the in-person version of the course,
the students observe demos to show off the importance of motion in vision, and color in vision.
Those demos aren&amp;rsquo;t available online; they only work in person.
The color vision demo puts students in a room without colored light, thereby only permitting gray-scale vision.
The importance of color then becomes immediately apparent, no pun intended; color is useful for distinguishing safe food from spoiled, and healthy faces from sickly ones.
This exercise helps motivate Marr&amp;rsquo;s theory of computation: that you can reason about brain function by thinking about what the brain must compute, and why.&lt;/p&gt;
&lt;p&gt;In a similar spirit to these demos,
there could also be a demo for the students showing what it&amp;rsquo;s like to have prosopagnosia.
This would help students feel more viscerally &amp;ldquo;what is computed and why&amp;rdquo; when it comes to facial recognition,
and it could also be used for people to better understand the condition.
Fostering empathy and understanding is always a good thing!&lt;/p&gt;
&lt;p&gt;How would we do it? With augmented reality, it would be possible to overlay or distort faces in a way that makes them unrecognizable.
The naive implementation would be to simply cover up all faces with a rectangle.
To make it a closer approximation of the prosopagnosia experience,
it would be essential to work with people with prosopagnosia.
Perhaps applying a light distortion to a face, but critically applying a different distortion to a face every time it is observed, would be a solid way to disrupt the user&amp;rsquo;s ability to recognize faces without being too distracting.
It&amp;rsquo;s difficult for me to know a priori whether this could create a convincing prosopagnosia experience,
so I will leave this snippet here, merely as food for thought, rather than pursuing the idea.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Do you think this effect could be convincing, approximating the experience of someone with prosopagnosia in someone without?&lt;/p&gt;
&lt;p&gt;In writing this snippet I Googled &amp;ldquo;prosopagnosia augmented reality&amp;rdquo; to see if anyone had tried this idea already.
Of course what I found was not my idea, but rather the reverse: using augmented reality to help those with prosopagnosia, rather than using it to help those without. That makes a lot of sense, and I feel a bit silly for it.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Maybe it could be a good class project for someone to dive deeper into this idea though. If you do, do let me know!! &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Amazon Beans: Only Pay for What You Eat</title>
      <link>https://davidbieber.com/snippets/2021-12-09-amazon-beans/</link>
      <pubDate>Thu, 09 Dec 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-12-09-amazon-beans/</guid>
      
      <description>&lt;p&gt;The idea is simple, it&amp;rsquo;s silly, but I think it has surprising depth.
It&amp;rsquo;s Amazon Beans: &amp;ldquo;only pay for what you eat&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Basically, I envision a new product from Amazon
(or any other retailer, but it feels like a very Amazon idea, as you&amp;rsquo;ll soon see):
a special case of cans of beans.
What makes it special?
You don&amp;rsquo;t have to pay anything to receive the case.
You only pay for the cans of beans that you remove from the case.&lt;/p&gt;
&lt;p&gt;So, the actual tagline would be &amp;ldquo;only pay for what you open&amp;rdquo;,
but I thought &amp;ldquo;only pay for what you &lt;em&gt;eat&lt;/em&gt;&amp;rdquo; had a better ring to it,
and still describes the situation fairly accurately.&lt;/p&gt;
&lt;h4 id=&#34;straw-man-implementation-of-amazon-beans&#34;&gt;Straw man implementation of Amazon Beans&lt;/h4&gt;
&lt;p&gt;The implementation details are left to the retailer to determine, but I&amp;rsquo;ll put out a straw man just to provide evidence that the Amazon Beans idea is possible to put into practice.
Here&amp;rsquo;s the straw man:
The buyer must provide payment details to get the case of Amazon Beans, but they are not charged anything up front.
The case of Amazon Beans is internet connected, with little sensors that indicate
when cans of beans are removed.
The purchaser of the case agrees to pay for any beans that are removed from the case. And if for some reason the case cannot phone home for a while, e.g. because it&amp;rsquo;s thrown in a Faraday cage for a week or something like that, the purchaser will pay for the full case of beans.
If the beans are never eaten, they are never paid for&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.
Once they are eaten, they are considered purchased, but even then they don&amp;rsquo;t need to be paid for immediately; further deferred payment services are available as well.&lt;/p&gt;
&lt;h4 id=&#34;why-amazon-beans&#34;&gt;Why Amazon Beans?&lt;/h4&gt;
&lt;p&gt;Possible consequences of an Amazon Beans program include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ending world hunger&lt;/li&gt;
&lt;li&gt;Increasing global resilience to supply chain shocks&lt;/li&gt;
&lt;li&gt;Further cementing Amazon&amp;rsquo;s market dominance&lt;/li&gt;
&lt;li&gt;Giving increased flexibility to people living paycheck to paycheck&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In one sense, Amazon Beans turns ordinary homes into an extended Amazon warehouse.
Since the beans can be delivered and consumed at vastly different points in time,
this adds flexibility to delivery logistics, acting as a shock-absorber of sorts for changes in supply chain and shipping.&lt;/p&gt;
&lt;p&gt;A family that lives paycheck to paycheck might not have sufficient funds to keep a reserve of extra food in their home if they have to pay for that food up front, but if the food is only paid for once it is eaten, this program might allow that family to maintain such a food reserve.
If they are temporarily between jobs, the food is still available without the hassle of having to take out a loan and go into debt to acquire it (kind of&amp;hellip; eating food you cannot afford is still like going into debt, but it ought to be a smoother experience and importantly it doesn&amp;rsquo;t leave the family &lt;em&gt;without food&lt;/em&gt; at any point).&lt;/p&gt;
&lt;h4 id=&#34;more-implementation-thoughts&#34;&gt;More implementation thoughts&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Internet connectivity&lt;/strong&gt;
When you get your first case of Amazon Beans (or when you order it),
you need to tell it how to connect to the internet.
You don&amp;rsquo;t need to do this for subsequent cases of beans though.
The internet connectivity information can be stored by Amazon and come
preconfigured on all future Amazon Beans cases that you order.
This way, when they arrive, you can just toss them on your shelf.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stockpiling&lt;/strong&gt;
Customers are by default only allowed to order a single case of Amazon Beans at a time, and only when they&amp;rsquo;ve consumed a certain fraction of that case can they order their next case.
(And if they opt in, that next case can be ordered automatically, at no cost to the consumer, when the first case is running low.)
This eliminates any worry Amazon might have about a single adversarial customer
ordering a large quantity of beans and letting them all go unused and unpaid for.
After a customer earns trust (e.g. by demonstrating they are a restaurant or that they consume beans in higher quantities), they can order a larger shipment of Amazon Beans cases.&lt;/p&gt;
&lt;h4 id=&#34;what-products-make-sense&#34;&gt;What products make sense?&lt;/h4&gt;
&lt;p&gt;Beans are a good candidate for the Amazon Beans model because they are inexpensive, ship well in bulk, have a long shelf life,
and have a predictable repeating consumption pattern.
Other products might make sense too.
Other foods like pastas, rice, canned foods, tea, powdered milk, jerky, etc have similarly long shelf-lives and could make sense.
Repeatedly consumed products like toothpaste, batteries, and toilet paper likely make sense too. These are the types of products that Amazon already encourages subscriptions for.&lt;/p&gt;
&lt;h4 id=&#34;tangent-dorm-supply&#34;&gt;Tangent: Dorm Supply&lt;/h4&gt;
&lt;p&gt;Related to Amazon Beans, but extended to a wider variety of products, we end up at the idea of a low-cost / no-money-down reseller. Instead of considering this in the context of a single household, let&amp;rsquo;s consider the lobby of an 80-person dormitory. The dorm manager orders (at no cost to the dorm) products that the students living there are likely to use. The students are only charged if they take the product. When summer comes, unused product is returned or saved for the following year. If the product has a limited shelf-life, unconsumed product is disposable at no cost at the end of the shelf-life.&lt;/p&gt;
&lt;h4 id=&#34;risks-and-risk-mitigation&#34;&gt;Risks and Risk Mitigation&lt;/h4&gt;
&lt;p&gt;The primary risk to Amazon is that product is ordered but goes unconsumed, and therefore is never paid for.
The anti-stockpiling measure described above takes one step to mitigate this risk.
I don&amp;rsquo;t actually think the risk is that large, but of course it would be necessary to model and monitor this risk if putting the Amazon Beans program into production.
Another risk mitigation measure is that
Amazon could charge a small nominal fee for the first case of Amazon Beans. Adding this entry fee for the program will prevent people from ordering cases of beans that they have no intention of consuming.
This fee could even go toward the costs of the beans, so it doesn&amp;rsquo;t even feel like a fee to the consumer.&lt;/p&gt;
&lt;p&gt;Another risk of the program is
it comes with a feeling of spending associated with each can opened.
This is not good for the consumer&amp;rsquo;s mental health,
and it discourages consumption. Feeling like you&amp;rsquo;re spending money every time you go to eat in your own house is an uncomfortable situation.
Feeling like your eating habits are being monitored is similarly uncomfortable.
I don&amp;rsquo;t have any mitigation strategies to offer for these issues at this time.&lt;/p&gt;
&lt;p&gt;Another risk comes in scaling to many products. If ordering a case of a product is truly no cost to a consumer, they would order a case of every possible product.
That doesn&amp;rsquo;t work as the product offerings soar to thousands of products.
Having the nominal up-front cost mentioned above, which goes toward the cost of the first units of the product consumed, mitigate this and allow for scaling.&lt;/p&gt;
&lt;p&gt;Finally, a consumer&amp;rsquo;s tastes may change. They may have a case of a product they don&amp;rsquo;t want to consume ever again. Being able to return large quantities of a product is important for situations like this.&lt;/p&gt;
&lt;h4 id=&#34;directions-for-future-snippets&#34;&gt;Directions for Future Snippets&lt;/h4&gt;
&lt;p&gt;In a future snippet it would be interesting to consider the costs and benefits to Amazon and to the consumer of an Amazon Beans program.
I expect we&amp;rsquo;ll find that if the cost of internet connectivity is modest relative to the cost of a case of beans, this becomes a win-win for a large segment of consumers and for Amazon.
Some costs to consider include spoilage and other lost beans, customer service, cost of beans, shipping costs, software costs, and of course the cost of the special internet-connected case.&lt;/p&gt;
&lt;p&gt;In a future snippet I&amp;rsquo;d also like to think through whether I&amp;rsquo;m a proponent of the idea. What are the longer term consequences? What ethical issues arise?&lt;/p&gt;
&lt;p&gt;Brainstorming fun names comes later too. Jeffrey Beanzos? I&amp;rsquo;ll keep thinking.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;The shelf-life of beans tends to be 2-5 years, so the policy can be something like: &amp;ldquo;If the beans remain uneaten for 5 years, you get to keep the beans for free. Dispose of them responsibly.&amp;rdquo; &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>The Future of Automation Software</title>
      <link>https://davidbieber.com/snippets/2021-12-07-future-automation-software/</link>
      <pubDate>Tue, 07 Dec 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-12-07-future-automation-software/</guid>
      
      <description>&lt;p&gt;
&lt;a href=&#34;https://browserflow.app&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Browserflow&lt;/a&gt; is great.
It&amp;rsquo;s beyond great.
It&amp;rsquo;s one of my favorite tools, because it is so versatile and empowering.&lt;/p&gt;
&lt;p&gt;Nevertheless, there&amp;rsquo;s more that I want from my automation tools.
Here&amp;rsquo;s a summary of what I&amp;rsquo;d like:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;OS-level actions&lt;/li&gt;
&lt;li&gt;Per-application actions&lt;/li&gt;
&lt;li&gt;Per-website actions&lt;/li&gt;
&lt;li&gt;Computer vision guided actions&lt;/li&gt;
&lt;li&gt;Natural language action specification&lt;/li&gt;
&lt;li&gt;Automatic action discovery&lt;/li&gt;
&lt;li&gt;Automatic automation extraction&lt;/li&gt;
&lt;li&gt;User-triggered, event-triggered and time-triggered automations&lt;/li&gt;
&lt;li&gt;A great sharing experience&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;os-level-actions&#34;&gt;OS-level actions&lt;/h4&gt;
&lt;p&gt;Browserflow is (appropriately) limited in scope.
It allows automating the Browser, and that&amp;rsquo;s it.
I would like to be able to use a Browserflow-like system to automate the Browser as well as everything else on my computer.
In the idealized hypothetical future I&amp;rsquo;m constructing here, I don&amp;rsquo;t need to think about the boundaries between applications and operating system when I construct an automation.&lt;/p&gt;
&lt;p&gt;Example OS-level actions include launching applications, switching between open windows of different applications, closing applications, switching between Desktops, and resizing windows.&lt;/p&gt;
&lt;p&gt;Mac&amp;rsquo;s Automator software is a good example of an automation tool that supports OS-level actions, but (to my knowledge) it does not then also provide a good browser automation experience.&lt;/p&gt;
&lt;p&gt;An example automation that takes advantage of these actions is setting up a series of windows just the way I like them (today achievable with software like 
&lt;a href=&#34;https://manytricks.com/moom/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Moom&lt;/a&gt;).
Combined with per-application actions (next section), these actions allow for powerful multi-application automations.&lt;/p&gt;
&lt;h4 id=&#34;per-application-actions&#34;&gt;Per-application actions&lt;/h4&gt;
&lt;p&gt;The range of activities people perform on computers is extremely wide.
Each application has different actions that are possible to take in it.
I would like for automation software to reflect this.&lt;/p&gt;
&lt;p&gt;Photo editing applications can provide actions for photo editing,
word processing applications should have their own domain-specific actions,
and gaming and music applications should similarly provide their own.&lt;/p&gt;
&lt;p&gt;This is somewhat reflected in the state of things today in Automator.
For some software, there are actions available allowing programmatic control of the application.
Today, these actions must be provided by the application developer.&lt;/p&gt;
&lt;p&gt;We should go beyond this; ordinary users should be able to make actions for a piece of software and share them with other users of that software.
The actions provided by the application developer that Automator can access today are often insufficient.
But developing a new action does not need to be a difficult endeavor.&lt;/p&gt;
&lt;p&gt;An action developer should be able write a parameterized action that (1) verifies the application meets any preconditions necessary for performing the action, (2) uses menu items, buttons, the mouse and keyboard, and visual indicators (3) in order to perform a sequence of sub-actions in the application to achieve the action&amp;rsquo;s overall intended behavior.
Sharing these actions with others who might use them in broader automations should be possible on GitHub or through any other means (e.g. an actions repository or actions store, for example, either of which would allow browsing actions by application.)&lt;/p&gt;
&lt;p&gt;Critically, I would like these OS-level and application-level actions to be available in the same software as the browser-level and website-level actions that a tool like Browserflow provides.&lt;/p&gt;
&lt;p&gt;Much of my computer activity happens in the browser, text editor, and the terminal. If this trend away from desktop applications toward browser-usage is taking place for everyone, OS-level and application-level actions may be less important than what we discuss next: per-website actions, vision-based actions, and automatic action discovery.&lt;/p&gt;
&lt;h4 id=&#34;per-website-actions&#34;&gt;Per-website actions&lt;/h4&gt;
&lt;p&gt;Some applications, particularly browsers, do not have a clear fixed set of actions that make sense, because they can render many websites.
Each website has different things you can do on it.&lt;/p&gt;
&lt;p&gt;So, similar to the per-application actions proposed in the previous section,
I&amp;rsquo;d also like to call for per-website actions.
DK, consider this a Browserflow feature request.&lt;/p&gt;
&lt;p&gt;In Browserflow, a user can define a flow and call that flow from another flow.
This isn&amp;rsquo;t the most well-developed feature of Browserflow;
developing and debugging flows like this requires a lot of clicking around, and it&amp;rsquo;s hard to see what you&amp;rsquo;re doing during development.
Nevertheless, it&amp;rsquo;s a powerful feature that is the seed of per-website actions.&lt;/p&gt;
&lt;p&gt;That you can use a flow as an action in Browserflow means you can define flows
for individual activities you might perform on a website, and use them repeatedly in many different flows pertaining to that website.
Browserflow also allows sharing flows, but there&amp;rsquo;s no central repository of them yet, so it is taking solid but small steps toward the dream of user-friendly discoverable per-website actions.&lt;/p&gt;
&lt;p&gt;Since every website has different actions to perform on it, and website authors do not provide these actions,
it is somewhat surprising that browser automation leads the automation scene in terms of its capabilities. The saving grace here is that websites conform to standards and expose structure that automation software can take advantage of, which desktop applications do not provide. Browser automation software uses CSS and XPATH selectors to take advantage of this uniformity to provide a decent automation experience.
For desktop software, or for websites that are not built in a tool-friendly manner, we turn to our next feature-request for automation software, vision-guided actions.&lt;/p&gt;
&lt;h4 id=&#34;computer-vision-guided-actions&#34;&gt;Computer vision guided actions&lt;/h4&gt;
&lt;p&gt;All the actions in automation software today operate on clearly defined data structures, but there is so much more that&amp;rsquo;s possible using computer vision.
Actions that work on websites rely on CSS or XPATH queries to find the appropriate part of the page to manipulate.
Computer vision based actions can work in places where there is no DOM, and hence no notion of CSS or XPATH selectors.&lt;/p&gt;
&lt;p&gt;An example of a computer vision based action is &amp;ldquo;Find the text X&amp;rdquo;. Here, X is a parameter. When run, the action identifies the location of the screen containing the text X. The beauty is that X doesn&amp;rsquo;t need to be on a webpage or in a text field. Even if X is stylized, part of a pdf, or part of an image, the action will still work. This action can be followed up with &amp;ldquo;Click&amp;rdquo; or &amp;ldquo;Screenshot&amp;rdquo; actions, that use the location found from the &amp;ldquo;Find the text X&amp;rdquo; action as a parameter.&lt;/p&gt;
&lt;p&gt;Another example of a computer vision based action is &amp;ldquo;Find a region visually similar to X&amp;rdquo;. This action is parameterized by an image, and it finds the location of that image (or similar) on the screen. This might be useful for automating a game with a custom graphic that you have to interact with; it doesn&amp;rsquo;t matter if that game doesn&amp;rsquo;t provide any semantic elements like buttons or a DOM, the computer vision actions will still admit automation.&lt;/p&gt;
&lt;p&gt;I found computer vision guided actions useful when building 
&lt;a href=&#34;https://github.com/dbieber/ScrabbleBot&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Scrab Blebot&lt;/a&gt;, a Scrabble-playing bot that could play Words With Friends on Facebook.
The bot looked for regions of the screen visually similar to an image of a Scrabble tile with a letter on it in order to figure out where to click and drag.
I had to build my own one-off actions for this project though; there was no automation software with vision-based actions available for me to use when developing this project ten (!) years ago.&lt;/p&gt;
&lt;h4 id=&#34;natural-language-action-specification&#34;&gt;Natural language action specification&lt;/h4&gt;
&lt;p&gt;&amp;ldquo;Click the submit button.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Copy the first paragraph.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;So far we have only spoken about allowing developers to define actions. In the next section we will move on to automatic action discovery &amp;ndash; where an action is detected and defined automatically by an algorithm, rather than being defined by a human.
Natural language action specification fits nicely in between these two categories.
The idea here is that we can map human natural language to an action.&lt;/p&gt;
&lt;p&gt;If the user says &amp;ldquo;Click the submit button&amp;rdquo;, we can use machine learning to infer that this translates to a single action &amp;ldquo;Click&amp;rdquo; parameterized by the selector &amp;ldquo;.submit&amp;rdquo; (or whatever the appropriate selector is for the current page).&lt;/p&gt;
&lt;p&gt;If the user says &amp;ldquo;Copy the first paragraph&amp;rdquo;, again machine learning can translate this into one or more actions that achieves the task.
Large language models will be instrumental in making this feature production quality. See for example the 
&lt;a href=&#34;https://www.youtube.com/watch?v=SGUCcjHTmGY&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Codex demo&lt;/a&gt; for a taste of the capabilities of large language models in this domain.&lt;/p&gt;
&lt;h4 id=&#34;automatic-action-discovery&#34;&gt;Automatic action discovery&lt;/h4&gt;
&lt;p&gt;We next move on to a research-level feature request: automatic action discovery.
There are billions of websites and software applications, each with its own user interface and its own set of possible actions.
It&amp;rsquo;s unreasonable to expect that a developer will construct actions for each and every one of these, but that doesn&amp;rsquo;t mean we can&amp;rsquo;t use machine learning to detect actions automatically.&lt;/p&gt;
&lt;p&gt;There are two types of signal that are useful for automatically detecting actions: (1) similarity in user interface to known actions, and (2) observing user behavior.&lt;/p&gt;
&lt;p&gt;(1) Though each website and application has its own UI, there are common patterns. Taking advantage of these common patterns, an algorithm might be able to discern that a website or application provides certain actions simply from its UI elements and arrangement.&lt;/p&gt;
&lt;p&gt;(2) By observing user behavior on a website or application (and comparing it with behaviors exhibited previously), an algorithm might be able to detect actions available on that website or application even when method (1) falls short (or in combination with method (1)).&lt;/p&gt;
&lt;p&gt;Critical to doing automatic action discovery well is figuring out how to parameterize the discovered actions.
In many cases this is easy; when filling out a form on a website, the text typed is the parameter, while the location in the form is a core part of the action.
In other cases, it&amp;rsquo;s less clear cut; in a shell, typing a command is part of an action, while typing an argument to the command is a parameter, but these are comprised of similar low-level actions (typing characters).
This is an interesting research challenge to get right.&lt;/p&gt;
&lt;h4 id=&#34;automatic-automation-extraction&#34;&gt;Automatic automation extraction&lt;/h4&gt;
&lt;p&gt;The pièce de résistance of future automation software is automatic automation extraction.
Software will one day automatically notice when something you&amp;rsquo;re doing can be automated, and it will offer to automate it for you.
It might notice this because (1) you&amp;rsquo;re engaging in a repeated behavior.
Or it might notice this because (2) you&amp;rsquo;re engaging in a behavior similar to one it&amp;rsquo;s seen before (e.g. from data collected from other users earlier).&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s important that anyone working on automatic automation extraction respect user privacy.
The data that would be most useful for this type of project (broad computer usage data) is extremely sensitive.
It is an interesting research direction to work toward this goal of automatic automation extraction in a way that consumes little data, and which can be deployed in a privacy preserving manner.&lt;/p&gt;
&lt;h4 id=&#34;user-triggered-event-triggered-and-time-triggered-automations&#34;&gt;User-triggered, event-triggered and time-triggered automations&lt;/h4&gt;
&lt;p&gt;I conclude with a more modest request than the previous two machine learning based feature requests: triggers.&lt;/p&gt;
&lt;p&gt;As I see it, a good trigger experience is what makes or breaks the value of automation software. This is because the triggers are the largest potential source of friction for a user of automations, outside of constructing the automation to begin with.&lt;/p&gt;
&lt;p&gt;For user-triggered automations (automations instigated by a user),
I really liked the typeahead UI that Browserflow initially used.
I remain hopeful that DK will bring that back.
Keyboard shortcuts are the other clear contender for a good triggering experience.&lt;/p&gt;
&lt;p&gt;Event-triggered automations are also extremely useful.
In my own day-to-day, I use email triggered automations (for handling emails from banks), and chat-triggered automations for all sorts of things.
If-this-than-that is probably an excellent source of inspiration for other events. You can also see 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-02-04-bieber-bot-capabilities/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;this list of Bieber Bot&amp;rsquo;s capabilities&lt;/a&gt; which breaks the capabilities down by whether they&amp;rsquo;re timer-triggered, chat-triggered, or credit-card-swipe-triggered.&lt;/p&gt;
&lt;p&gt;Time-triggered automations can be broken down further into one-off automations (e.g. &amp;ldquo;send this email tomorrow morning&amp;rdquo;) and recurring ones (&amp;ldquo;every morning, email me a digest with the news, weather, and a cat video to watch&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;Triggers don&amp;rsquo;t need to be provided directly by the same software that allows creating automations, but it is sensible to bundle these two things together, since automations are a common thing to want to trigger. Separate trigger software and automation software is in many ways actually desirable, but it is critical that the experience of setting up triggers for an automation be clean and user friendly.&lt;/p&gt;
&lt;h4 id=&#34;a-great-sharing-experience&#34;&gt;A great sharing experience&lt;/h4&gt;
&lt;p&gt;Finally, automation is a superpower, and so I want to be able to share it with others.
If I write a note-taking automation, I want my fellow note-takers to be able to use it.
If someone writes a Farmville automation tool, other Farmville players should be able to use it too.&lt;/p&gt;
&lt;p&gt;However, sharing comes with concerns: you don&amp;rsquo;t want to give untrustworthy strangers unfettered access to your machine. Arbitrary code execution is dangerous.&lt;/p&gt;
&lt;p&gt;So, my ideal sharing experience is a hybrid of &amp;ldquo;app store&amp;rdquo; and &amp;ldquo;GitHub&amp;rdquo;.
A curated collection of automations that are audited and trustworthy, easy to search, and easy to discover would be very welcome. If automations from this collection were automatically surfaced when I was browsing on a website that had such an automation built for it, I would be delighted.&lt;/p&gt;
&lt;p&gt;Then, for automations that haven&amp;rsquo;t gone through any vetting process, it should still be easy to share. It should be possible to host an automation on GitHub or to send an automation to a friend without ever needing a central body to vet the automation.&lt;/p&gt;
&lt;p&gt;By supporting both of these sharing models, we can ensure a healthy ecosystem of automations
useful both for programmers and automation builders, and for people who simply want to experience the joy of computing using the automations of others.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Interested in working on any of these aspects of automation software? Get in touch. I&amp;rsquo;m always eager to discuss.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Study Group for 9.13 The Human Brain</title>
      <link>https://davidbieber.com/snippets/2021-12-05-human-brain-study-group/</link>
      <pubDate>Sun, 05 Dec 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-12-05-human-brain-study-group/</guid>
      
      <description>&lt;p&gt;Interested in casually learning a bit of neuroscience?
I’m gathering a group to watch / discuss 
&lt;a href=&#34;https://www.youtube.com/playlist?list=PLUl4u3cNGP60IKRN_pFptIBxeiMc0MCJP&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;these lectures (MIT 9.13 The Human Brain, Spring 2019)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ping me if interested!&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how it&amp;rsquo;ll work.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll make a Discord.
Each participant will get a channel for dumping notes, thoughts, questions, whatever.
You&amp;rsquo;re free to proceed through the material at your own pace, and are encouraged to share thoughts etc. as you go.&lt;/p&gt;
&lt;p&gt;Each week I&amp;rsquo;ll check in with all participants
to see how far they&amp;rsquo;ve gotten and what their goals for the following week are.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll have (possibly asynchronous) discussions in Discord,
and every 2 weeks we&amp;rsquo;ll have a synchronous meet up (video/audio chat) with
(a) discussion questions and (b) and chance to ask questions and discuss ideas
with each other.
For these, we&amp;rsquo;ll use whenisgood to choose a time that works for the most people.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll continue for 6 weeks (3 synchronous meetups) and then reevaluate if we want to keep scheduling more.&lt;/p&gt;
&lt;p&gt;The course has 18 hours of lecture content, 12 weeks of readings, and 8 assignments.
Personally, I plan to spend about 3 hours on this material per week.
So, I&amp;rsquo;ll probably get through the video lectures but none of the other material (but I&amp;rsquo;ll adjust this plan as I go depending on what looks most interesting).
You&amp;rsquo;re welcome to do the same, or to approach the material in a different way as you see fit.&lt;/p&gt;
&lt;p&gt;Additionally, when I go to watch the lectures, I&amp;rsquo;ll post that on the Discord too. If folks are available they can join me. I encourage others to do the same, or to meet up to watch lectures in small groups. I find it can be easier to learn when watching with someone else and pausing to discuss periodically.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Draft Instructions for Flashcard Collection Task</title>
      <link>https://davidbieber.com/snippets/2021-11-23-flashcard-collection-task/</link>
      <pubDate>Tue, 23 Nov 2021 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-11-23-flashcard-collection-task/</guid>
      
      <description>&lt;p&gt;Hello! This is a draft of instructions I intend to send out to volunteers for the contextual flashcard dataset collection project.
I would love your feedback on the instructions before I send them out more widely.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Welcome to the Contextual Flashcard Dataset Project.
Thank you for volunteering!
By working together, we are assembling a dataset of thousands of in-context flashcards
to help evaluate and improve future automatic flashcard generation projects.&lt;/p&gt;
&lt;p&gt;To get started, install the Browserflow extension and the flow:
&lt;a href=&#34;https://browserflow.app/shared/1b2b5231-5f96-4f73-87a6-006626fa3831&#34;&gt;https://browserflow.app/shared/1b2b5231-5f96-4f73-87a6-006626fa3831&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Your help is requested in creating flashcards to populate the dataset.
Please submit between 5 and 200 flashcards that you believe would be useful or interesting to you.
The flow above will assist you in submitting flashcards to the dataset.&lt;/p&gt;
&lt;p&gt;To submit a flashcard for the dataset:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Browse the web as normal.&lt;/li&gt;
&lt;li&gt;Select some text you consider important.&lt;/li&gt;
&lt;li&gt;Run the 
&lt;a href=&#34;https://browserflow.app/shared/1b2b5231-5f96-4f73-87a6-006626fa3831&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Create Flashcard Entry flow&lt;/a&gt;; it will open the Create Flashcard Entry form and pre-populate it for you.&lt;/li&gt;
&lt;li&gt;Make any desired changes to the &amp;ldquo;Flashcard Front&amp;rdquo; and &amp;ldquo;Flashcard Back&amp;rdquo; fields in the Create Flashcard Entry form.&lt;/li&gt;
&lt;li&gt;Submit the form.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In lieu of using Browserflow, you may also submit 
&lt;a href=&#34;https://forms.gle/vTNWReM6qeEwX6GDA&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;the data entry form&lt;/a&gt; manually.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&#34;how-will-the-data-be-used&#34;&gt;How will the data be used?&lt;/h3&gt;
&lt;p&gt;The dataset will be cleaned. Personal information or offensive language will be removed. The resulting dataset will be made public for anyone to use.&lt;/p&gt;
&lt;h3 id=&#34;when-are-submissions-open&#34;&gt;When are submissions open?&lt;/h3&gt;
&lt;p&gt;We will begin collecting submissions on December 1, 2021, and leave submissions open for 2 months, closing submissions on January 31, 2022.&lt;/p&gt;
&lt;h3 id=&#34;what-flashcards-should-i-submit&#34;&gt;What flashcards should I submit?&lt;/h3&gt;
&lt;p&gt;That&amp;rsquo;s up to you! Still asking? Here&amp;rsquo;s some guidance:&lt;/p&gt;
&lt;p&gt;Submit any flashcards that you would (1) find personally interesting or useful, and (2) only contain public information.&lt;/p&gt;
&lt;p&gt;Interesting facts from Wikipedia or articles you read online are a good idea.
Private information about close friends is not.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>BIRDS: Bidirectional incremental real-time data synchronizers</title>
      <link>https://davidbieber.com/snippets/2021-11-20-birds/</link>
      <pubDate>Sat, 20 Nov 2021 02:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-11-20-birds/</guid>
      
      <description>&lt;p&gt;The culmination of my thinking on note-taking interoperability so far is that we need &lt;strong&gt;BIRDS&lt;/strong&gt;. 🐦. Allow me to explain.&lt;/p&gt;
&lt;p&gt;We want an &amp;ldquo;intermediate representation&amp;rdquo; for note-taking systems, to allow them to interoperate.&lt;/p&gt;
&lt;p&gt;Here an &amp;ldquo;intermediate representation&amp;rdquo; means an &lt;strong&gt;in-process&lt;/strong&gt; representation of notes that can do &lt;strong&gt;bidirectional real-time incremental&lt;/strong&gt; syncs with any of the popular note-taking systems (any system with a connector written for it).
The main reason we want this is it allows application developers to write applications once for the IR, and have their application work for users using any note-taking system.
A second reason this is desirable is it allows introducing data into your notes from multiple sources, like your email, news feeds, messages, and social media accounts.&lt;/p&gt;
&lt;p&gt;To bridge a note-taking system with the IR, a connector should be written between the system and the intermediate representation. These connectors, we shall call &lt;strong&gt;birds&lt;/strong&gt;, 🦤, short for &amp;ldquo;bidirectional incremental real-time data synchronizer&amp;rdquo;. Each bird 🐔 is a bridge that either pushes, pulls, or pushes-and-pulls data between the &amp;ldquo;intermediate representation&amp;rdquo; notebase and some data source or storage system.&lt;/p&gt;
&lt;p&gt;Birds 🦚 are bidirectional because they allow pushing or pulling data in either direction.
They are incremental because they are aware of what data is on the other end of the connection, and only transmit changes.
They are real-time, because these changes are transmitted quickly and automatically.
These properties are similar to those of Dropbox or Google Drive, but rather than there being files on either end of the connection, there are notes.&lt;/p&gt;
&lt;p&gt;What are the birds 🦜 that I would use for my current setup?&lt;/p&gt;
&lt;p&gt;I would use a bidirectional bird 🦃 with Roam Research, since that&amp;rsquo;s my core note-taking location at the moment.
I would use a bird 🐤 to connect my email to my notes. Ideally I would also have birds 🦉 for each of the messaging and social media platforms that I use too.
I would use a bird 🐧 to write my full notebase to disk locally.&lt;/p&gt;
&lt;p&gt;If later I switch away from Roam, I would use a new bird 🐓 to import my data into whatever new better system I switch to.&lt;/p&gt;
&lt;p&gt;Remarkably, I was able to put a bird 🦢 emoji next to every use of the word bird 🕊️ in this snippet, and still not run out of bird 🦆 emojis.&lt;/p&gt;
&lt;p&gt;🦅&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Save my spot! Finer-grained bookmarks for incremental reading</title>
      <link>https://davidbieber.com/snippets/2021-11-20-save-my-spot/</link>
      <pubDate>Sat, 20 Nov 2021 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-11-20-save-my-spot/</guid>
      
      <description>&lt;p&gt;When I find articles on the web, often I only read a small portion of an article before browsing away.
Instead of giving up on the article, I would like to leave a little visual marker on the page indicating the part of the page that I reached.
I&amp;rsquo;d then also like to automatically add a link to this marker to my notes.
So, if I&amp;rsquo;m ever reviewing my notes, I&amp;rsquo;ll be able to jump right back into the article where I left off.&lt;/p&gt;
&lt;p&gt;If I later continue reading the article, I&amp;rsquo;d like to move the marker to whatever spot I reach. (It&amp;rsquo;s OK if the old links keep linking to the old location, but I want a new link to whatever spot I&amp;rsquo;ve reached.)&lt;/p&gt;
&lt;p&gt;I think this should be possible to build with Browserflow. Let&amp;rsquo;s consider how.
I think I would do this with two flows, one to save my spot on a page (and add it to my notes),
and a second flow to restore to that spot on the page from the link in my notes.&lt;/p&gt;
&lt;p&gt;The biggest decision is how to represent a spot on a page. One option is the scroll position. Another option would be to remember a unique element id. Both approaches have drawbacks. Using scroll position doesn&amp;rsquo;t work well with dynamic content. Element ids aren&amp;rsquo;t guaranteed to be unique. I am leaning toward the scroll position approach to start, and then I&amp;rsquo;ll see how fragile it is. Even though it isn&amp;rsquo;t perfect, it will work in most situations.&lt;/p&gt;
&lt;p&gt;When I run the first flow, it will grab the URL of the current page and the current scroll position, and it will write that into my notes. This requires changing tabs, which is easy to do with Browserflow, but not easy to do with a standard JavaScript script. That flow will be run on the website where I am reading the article.&lt;/p&gt;
&lt;p&gt;The other flow will be run while I&amp;rsquo;m reading my notes. It would be great if just clicking on a link in my notes could trigger this flow and take me to the correct spot in the article, but this isn&amp;rsquo;t possible (by default) with Browserflow today. One way to work around this limitation of Browserflow is to write an always-on flow that listens for when I&amp;rsquo;ve clicked the link. Unfortunately, always-on flows are not great with Browserflow&amp;rsquo;s pricing plans.&lt;/p&gt;
&lt;p&gt;When I run the flow to restore my spot in an old article, the flow will first open a new tab to that article&amp;rsquo;s webpage. Then it will scroll to the specified position. When the flow starts, it will first need a way to determine which of the links on the notes page to follow. With the current version of Browserflow that I have (0.72 I think), you can just click on the link to specify this. This option is removed unfortunately in the latest version of Browserflow. Instead, we can probably use a clever selector to select the user-selected link. This should work in later Browserflow versions.&lt;/p&gt;
&lt;p&gt;Once these two flows are implemented, saving and loading my point in an article to and from my notes will become much easier. The next improvement will be adding in a bit of visual flourish (e.g. a visual marker in the article to draw my eye to where I left off). Certainly a smoother UX is feasible than the one I&amp;rsquo;ve planned here, but I think this Browserflow prototype hits a sweet spot of quality-to-effort ratio, and will be a satisfying prototype to build and use for myself.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Organizing a Twitter Discussion: Gathering Twitter Replies</title>
      <link>https://davidbieber.com/snippets/2021-11-20-twitter-replies/</link>
      <pubDate>Sat, 20 Nov 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-11-20-twitter-replies/</guid>
      
      <description>&lt;p&gt;I 
&lt;a href=&#34;https://twitter.com/Bieber/status/1461128201485402112&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;tweeted&lt;/a&gt; about spaced repetition earlier this week, sharing and summarizing 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-11-02-improvements-to-spaced-repetition/&#34;&gt;my latest snippet on the subject&lt;/a&gt;. A bunch of people left thoughtful replies, and I was quite pleased with the discussion. Now I want to look over the discussion holistically, but I don&amp;rsquo;t see a great way to do this. I don&amp;rsquo;t even see a way to look at all the replies to my thread in one place. I want to see not just this, but also replies to replies. TweetDeck might be able to help, but I don&amp;rsquo;t see how.&lt;/p&gt;
&lt;p&gt;I think what I&amp;rsquo;d like to do is write a little script that takes a tweet as input, and outputs links to all the replies and replies to replies in a little tree that I can put into Roam.
Then I can make notes on the full thread, and even link together different parts of the conversation.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s give this a try.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import twython
from messager import settings

client = twython.Twython(
        settings.TWITTER_CONSUMER_KEY,
        settings.TWITTER_CONSUMER_SECRET,
        settings.TWITTER_ACCESS_TOKEN,
        settings.TWITTER_ACCESS_TOKEN_SECRET)

def get_replies(status_id):
  status = client.lookup_status(id=status_id)[0]
  return get_replies_to_status(status)

def get_replies_to_status(status):
  status_id = status[&#39;id&#39;]
  screen_name = status[&#39;user&#39;][&#39;screen_name&#39;]
  results = client.search(
      q=f&#39;to:{screen_name}&#39;, sinceId=status_id, count=128)
  candidates = results[&#39;statuses&#39;]
  replies = []
  for candidate in candidates:
    if candidate[&#39;in_reply_to_status_id&#39;] == status_id:
      replies.append(candidate)
  return replies

def get_recursive_replies(status_id):
  status = client.lookup_status(id=status_id)[0]
  all_replies = []
  to_search = [status]
  searched = set()
  while to_search:
    status = to_search.pop()
    if status[&#39;id&#39;] not in searched:
      replies = get_replies_to_status(status)
      all_replies.extend(replies)
      to_search.extend(replies)
      searched.add(status[&#39;id&#39;])
  return all_replies

status_id = 1461128201485402112
replies = get_recursive_replies(status_id)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Aside: I would love for this file (the markdown file I&amp;rsquo;m writing this snippet in) to double as a Python file.
When I run it, just the Python code block(s) would get run.&lt;/p&gt;
&lt;p&gt;To my surprise the Twitter API did not make it easy to query for replies to a tweet. So, I&amp;rsquo;m using the workaround on display above.
To get all replies to a tweet, I query for all tweets to the tweet author, and then filter for those that are actually replies.
Since the number of search results is limited, this might not always work; it depends on what order Twitter decides to sort tweets by. If Twitter returns the oldest tweets first, this method will work consistently.&lt;/p&gt;
&lt;p&gt;It does seem to be working for now, fortunately. There are 60 recursive replies to my tweet, and with this method I was able to lay them all out in a row. Pasting the urls into Roam, I find the default rendering of each tweet in Roam takes up a bit too much space though and provides too much context. So, I may need to modify the display a bit more.&lt;/p&gt;
&lt;p&gt;My hope is that I can lay out the entire conversation compactly, and then start marking it up with my own notes, e.g. tagging replies that express similar ideas so I can reply to them together rather than individually.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Snippets in Other Languages</title>
      <link>https://davidbieber.com/snippets/2021-11-16-other-languages/</link>
      <pubDate>Tue, 16 Nov 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-11-16-other-languages/</guid>
      
      <description>&lt;p&gt;Bonjour, hello.&lt;/p&gt;
&lt;p&gt;Puedo escribir en otras linguas. No necessito escribir todos mis snippetos en Inglés. Como se dice &amp;ldquo;snippets&amp;rdquo; en Español? Parece que la palabra es fragmentos, pero la sección es mía, y puedo llamarlo lo que quiero. Por ahora, los llamaré &amp;ldquo;snippetos&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;En particular&amp;hellip; želim pisati na hrvatski. Svaki dan učim hrvatski, ali sam još uvijek beginner. Čitam easy-croatian.com za učenje. Radim flashcards i radim spaced repetition, ali ja sum na Chapter 17, a ima 100 Chapters.&lt;/p&gt;
&lt;p&gt;Hay mucho que aprender.&lt;/p&gt;
&lt;p&gt;Kako se kaže &amp;ldquo;beginner&amp;rdquo;, &amp;ldquo;chapter&amp;rdquo;, &amp;ldquo;17&amp;rdquo;, &amp;ldquo;100&amp;rdquo;, &amp;ldquo;flashcard&amp;rdquo;, i &amp;ldquo;spaced repetition&amp;rdquo; na hrvatski? Google Translate kaže &amp;ldquo;beginner&amp;rdquo; je &amp;ldquo;početnik&amp;rdquo;, &amp;ldquo;chapter&amp;rdquo; je &amp;ldquo;poglavlje&amp;rdquo;, &amp;ldquo;17&amp;rdquo; je &amp;ldquo;sedamnaest&amp;rdquo;, &amp;ldquo;100&amp;rdquo; je &amp;ldquo;sto&amp;rdquo;, &amp;ldquo;flashcard&amp;rdquo; je &amp;ldquo;flash kartica&amp;rdquo;, i &amp;ldquo;spaced repetition&amp;rdquo; je &amp;ldquo;razmaknuto ponavljanje&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Haré flash kartice para estas palabras.&lt;/p&gt;
&lt;p&gt;I think it&amp;rsquo;s absolutely wonderful that I can use snippets to practice writing in languages I&amp;rsquo;m not comfortable with. This would be so difficult with a traditional blog, because the readership wouldn&amp;rsquo;t be there, the comfort level wouldn&amp;rsquo;t be there. Try to imagine it: a traditional blog, or a blog with thousands of regular readers (or even dozens), sending out a post like this one. The audience wouldn&amp;rsquo;t be interested; they don&amp;rsquo;t speak the language the post is written it, and the quality is low. Most writers wouldn&amp;rsquo;t do it, and the audience wouldn&amp;rsquo;t respond well if they did.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t have those problems, and this brings me a lovely feeling of satisfaction. The snippets system is excellent to me. Of course, the trade-off is clear. There is no regular readership to be turned off by a post like this. To me, this is indubitably worthwhile.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Machine Learning Journal of Hypotheses</title>
      <link>https://davidbieber.com/snippets/2021-11-05-hypothesis-arxiv/</link>
      <pubDate>Fri, 05 Nov 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-11-05-hypothesis-arxiv/</guid>
      
      <description>&lt;p&gt;This snippet is about an idea for a new venue for publishing research hypotheses before any experiments have been carried out.
We can think of the idea as a &amp;ldquo;Hypothesis Journal&amp;rdquo; or &amp;ldquo;Hypothesis Arxiv&amp;rdquo;. Similar to how arxiv.org hosts pre-prints for scholarly articles, the Hypothesis Arxiv would be a venue for researchers to submit their research hypotheses for the research community to see and evaluate. As I&amp;rsquo;m interested in having this venue serve as a place for the community to not only submit, but also discuss and evaluate the hypotheses, &amp;ldquo;Hypothesis OpenReview&amp;rdquo; might be an even more fitting title.&lt;/p&gt;
&lt;p&gt;To narrow the scope of discussion, let&amp;rsquo;s confine ourselves to thinking about machine learning research for the time being. My hope is that such a venue would allow the machine learning community to more thoughtfully select the set of hypotheses it focuses on from year to year.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll aim to cover (1) why this is a good idea, (2) what it might look like, and (3) I&amp;rsquo;ll try to preempt some concerns one might have. We&amp;rsquo;ll also take a quick look at (4) similar ideas that have been tried in the past, and what we can learn from them.&lt;/p&gt;
&lt;h3 id=&#34;the-machine-learning-hypotheses-journal&#34;&gt;The &amp;ldquo;Machine Learning Hypotheses&amp;rdquo; Journal&lt;/h3&gt;
&lt;p&gt;The &amp;ldquo;Hypothesis Journal&amp;rdquo; idea is for a new venue that accepts scholarly submissions from researchers in the form of hypotheses, rather than complete research papers.
A hypothesis is generally a simpler and shorter artifact than a research paper.
Whereas a research paper includes a hypothesis together with experiments, their results, analysis, and conclusions, a hypothesis paper stops short of performing the proposed experiments.
It still contains the background and motivation, hypothesis, and proposed experiments, but does not perform those experiments, gather any new data, or form any conclusions about the veracity of the hypothesis.&lt;/p&gt;
&lt;p&gt;Once hypothesis papers are submitted, they are assigned reviewers.
Reviewers evaluate hypothesis along various dimensions for their scientific merit, allowing those hypothesis that seem most promising (e.g. interesting, plausible and potentially surprising, ethical, and likely impactful) to rise to the top.&lt;/p&gt;
&lt;p&gt;In addition to the standard review period, an important piece of the idea is opening up discussion to the machine learning community at large. The difference here is that the official reviewers are selected because they are trusted experts in the same field as the hypothesis paper, whereas the public discussion is open to anyone.&lt;/p&gt;
&lt;p&gt;The hope is that through the expert reviews and the community discussions, strong hypotheses can be identified and rewarded, and all hypotheses can see sunlight that allows them both to improve and inspire.&lt;/p&gt;
&lt;p&gt;Since hypothesis papers take less effort and less time to produce, a researcher might produce and submit several hypothesis papers to the &amp;ldquo;Hypothesis Journal&amp;rdquo; in a single cycle. I am also hopeful that each hypothesis can be assigned a greater number of reviewers than conference papers typically are.
This would allow the variance of the reviewer pool to diminish a little, and for each hypothesis to receive valuable signal from a variety of reviewers as to its merits.&lt;/p&gt;
&lt;p&gt;To make the idea concrete, let&amp;rsquo;s call the journal &amp;ldquo;Machine Learning Hypotheses&amp;rdquo;. And let&amp;rsquo;s further say it has an annual submission deadline, and a short review cycle followed by a conference.&lt;/p&gt;
&lt;h3 id=&#34;motivation&#34;&gt;Motivation&lt;/h3&gt;
&lt;p&gt;The pace of machine learning research is accelerating. Certain types of machine learning research are becoming increasingly expensive to perform (e.g. training large scale language models), prohibitively so for some researchers. A result of this is that there are far more hypotheses to test than resources available to test them. So, choosing wisely what hypotheses we investigate is increasingly important.&lt;/p&gt;
&lt;p&gt;The current publication model incentives publication of complete results.
Researchers come together at conferences to discuss findings. It&amp;rsquo;s at this point that the most significant mixing of ideas occurs.
In a flow diagram, the scientific process looks like roughly like this, with the greatest discussion and mixing of ideas currently taking place at the point marked (♥), while I am proposing increasing our focus on the point marked (¿):&lt;/p&gt;
&lt;p&gt;[Observations (from scientific literature, experiments, etc.)]
&lt;br/&gt;➔ [Hypothesis (¿)]
&lt;br/&gt;➔ [Experiments]
&lt;br/&gt;➔ [Results]
&lt;br/&gt;Path 1: ➔ [Success] ➔ [Write up paper (♥)]
&lt;br/&gt;Path 2: ➔ [Failure (✝)] ➔ [Go to start. Revise Hypothesis]&lt;/p&gt;
&lt;p&gt;(♥): It is primarily at (♥), when a hypothesis has been confirmed, that the research community comes together en masse to discuss the findings. This takes place through publications, conferences, and journals.&lt;/p&gt;
&lt;p&gt;(✝): I have seen proposed on several occasions that there be more opportunities for publishing negative results, and I support these proposals. That amounts to greater discussion taking place at (✝), e.g. through the introduction of &amp;ldquo;Negative Result Journals&amp;rdquo;. This is not what I am proposing though; I am proposing increasing our community focus on (¿), when hypotheses are formed but not yet tested.&lt;/p&gt;
&lt;p&gt;(¿): My proposal is that we have a forum for publishing and evaluating hypotheses, even before experiments have been run and data has been collected, thereby increasing the amount of discussion of ideas that takes place at the spot marked (¿) in the ongoing cycle of the scientific method.&lt;/p&gt;
&lt;p&gt;The main benefit of increasing publication and discussion at the hypothesis stage of the scientific process is the potential to &lt;strong&gt;more selectively and thoughtfully shape the collective portfolio of hypotheses that the research community as a whole pursues&lt;/strong&gt;. It does this through a few mechanisms. I would summarize them as (1) &lt;strong&gt;quantity&lt;/strong&gt;: increasing the range and number of ideas generated, (2) &lt;strong&gt;quality&lt;/strong&gt; and (3) &lt;strong&gt;coordination&lt;/strong&gt;: improving the quality and diversity of research pursued through discussion, and (4) &lt;strong&gt;speed&lt;/strong&gt;: tightening the feedback loop between when an idea is generated and when downstream ideas based on it are generated.&lt;/p&gt;
&lt;h5 id=&#34;1-quantity&#34;&gt;(1) Quantity&lt;/h5&gt;
&lt;p&gt;It is much easier to submit a hypothesis than to submit a full research paper. Therefore a &amp;ldquo;hypothesis arxiv&amp;rdquo; or &amp;ldquo;hypothesis journal&amp;rdquo;, if adequately popular and prestigious, could substantially increase the number of ideas proposed and discussed widely compared with the number seen in publications today.&lt;/p&gt;
&lt;p&gt;Compared with writing up a hypothesis, actually performing experiments, collecting data, performing analysis, and drawing conclusions is a considerable amount of work. Some individual researchers might be able to submit a few times, up to perhaps a full order of magnitude, more high quality hypotheses than complete research projects. These might include ideas the researcher would never have time to pursue fully on their own, but which the community could benefit from greatly.&lt;/p&gt;
&lt;p&gt;By attaching credit and prestige to submitting hypothesis, we make it possible to split the role of researcher into two sub-roles. One sub-rule is the idea generator/&amp;ldquo;hypothesizer&amp;rdquo;, and the other is the &amp;ldquo;experimentalist&amp;rdquo;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; that evaluates the hypothesis. This would enable some researchers to specialize into one of these two categories (while many researchers could continue operating both roles concurrently). Today, a successful research career requires mastering both of these skill sets. A prestigious &amp;ldquo;hypothesis journal&amp;rdquo; could reduce this pressure, perhaps allowing for people to make careers out of just one skill set of the other, more than is possible today.&lt;/p&gt;
&lt;p&gt;Importantly, researchers would be able to submit hypotheses about experiments that they may be unable to carry out on their own. Take the case of training large language models as an example. This is a prohibitively expensive task for many research organizations. Even if you cannot train a large language model yourself, you can still learn about them and produce informed hypotheses about them.
So, the best ideas about large language models could come from someone not in a position to run the experiments themselves.
The &amp;ldquo;hypothesis arxiv&amp;rdquo; idea would allow these researchers to still play a vital role in the research process.
This idea could significantly expand the number of researchers who can participate in large language model research, even if many of them can only participate at the hypothesis stage&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h5 id=&#34;2-quality&#34;&gt;(2) Quality&lt;/h5&gt;
&lt;p&gt;By moving the discussion of hypotheses as a community earlier in the cycle of the scientific method, we can be more selective and focused in what hypotheses we dedicate significant resources to.
Ideas that are obviously true or obviously false can be identified by the review process; these ideas need not consume significant effort by the community. The best ideas will be identified as such, and lower quality ideas can improve through the feedback they receive during review and discussion. By getting more viewpoints involved in selecting and evaluating ideas, the best ideas (to a wider range of researchers) will rise to the top and garner more attention.&lt;/p&gt;
&lt;p&gt;When a hypothesis finally is confirmed or rejected, since it will already have been discussed by the community, we will also have a &lt;em&gt;more accurate idea of how surprising the result truly is&lt;/em&gt;. Without this discussion first, we can only use hindsight to estimate how surprising findings are. This is an important idea, which other research communities adopt partially through the concept of pre-registration, but which is somewhat lacking in machine learning research today.&lt;/p&gt;
&lt;h5 id=&#34;3-coordination&#34;&gt;(3) Coordination&lt;/h5&gt;
&lt;p&gt;Putting hypotheses out in public before running experiments also allows for improved coordination. In particular, it can &lt;em&gt;decrease overlap&lt;/em&gt; in ideas pursued. This can in turn allow more different research directions to be pursued.&lt;/p&gt;
&lt;p&gt;Additionally, improved coordination can allow for the formation of larger efforts around the most promising directions. For example, if a researcher proposes a large language model experiment that is promising but which they cannot evaluate themself, a large research org might choose to work directly with that researcher to collaboratively evaluate the hypothesis.&lt;/p&gt;
&lt;h5 id=&#34;4-speed&#34;&gt;(4) Speed&lt;/h5&gt;
&lt;p&gt;There are two senses in which the hypothesis journal could accelerate the research process. One is by allowing new ideas to be born sooner, and the second is by increasing competition.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Tighter iteration cycle&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Today an idea doesn&amp;rsquo;t spawn child ideas until it is published, which comes after the experiments have been run and the hypothesis evaluated.
In principle, these child ideas could be born much sooner if the hypothesis were shared sooner, even if the hypothesis has not been demonstrated true yet.
Of course the amount of downstream work that can be done is limited before a result has been confirmed, but it is limited in how limited it is.&lt;/p&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Competition to evaluate ideas&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For the &amp;ldquo;hypothesis journal&amp;rdquo; idea to work, there has to be some prestige or other motivations attached to submitting surprising, useful, high quality hypotheses that turn out to be true (or false in an interesting way). Even so, there will still be lots of motivation remaining for the groups that actually carry out the experiments and confirm or reject the hypotheses. Once a strong hypothesis paper has been submitted, the idea is public, and if it is a good idea there could be competition to evaluate the idea as quickly as possible.&lt;/p&gt;
&lt;h5 id=&#34;other-benefits&#34;&gt;Other benefits&lt;/h5&gt;
&lt;p&gt;Those four factors (quantity, quality, coordination, and speed) collectively suggest the hypothesis journal could accelerate the pace of machine learning research, and improve the quality of the collective portfolio of projects of the machine learning community. Other possible benefits of a hypothesis journal include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Increasing representation. (e.g. allowing groups to partake in the research process even when running experiments may be prohibitively expensive)&lt;/li&gt;
&lt;li&gt;Lowering the barrier to writing, thinking through thoroughly, sharing, and discussing ideas.&lt;/li&gt;
&lt;li&gt;Decoupling incentives, which could lead to more honest science. Specifically, if people are evaluating the hypotheses of others rather than their own hypotheses, then negative results suddenly become less unappealing. I could see this acting as a force that e.g. reduces p-hacking. Pre-registering ideas also comes with statistical benefits even if you&amp;rsquo;re the same person submitting the idea and doing the experimental science, because it reduces cherry-picking of results and similar effects.&lt;/li&gt;
&lt;li&gt;Decoupling the skill sets of hypothesizer from experimenter has value as well. It allows people to specialize, focusing their skill set and becoming better at their selected role.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;a-strong-hypothesis&#34;&gt;A Strong Hypothesis&lt;/h4&gt;
&lt;p&gt;What constitutes a complete hypothesis? What feedback can reviewers / the community provide about a hypothesis?&lt;/p&gt;
&lt;p&gt;When a researcher submits a &amp;ldquo;hypothesis paper&amp;rdquo;, it should be similar to a research paper that stops abruptly after proposing experiments, rather than continuing on to execute the experiments and analyze the results.&lt;/p&gt;
&lt;p&gt;It should include the hypothesis, stated precisely in a falsifiable way. It should motivate why it is a reasonable thing to believe, and why the authors expect it to be true, as well as why we do not already know that it is true. It should propose specific experiments, that in principle could be carried out (although perhaps at a budget exceeding that of the authors) to evaluate the hypothesis. It should include in the description of the experiments precisely what would be measured and why.&lt;/p&gt;
&lt;p&gt;My description here is perhaps a bit myopic, and the types of hypotheses researchers might submit might not conform to this set of criteria precisely, but I hope this conveys the sense of hypotheses that I have in mind. In a future snippet I can think at greater length about exactly what criteria make for a strong hypothesis.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a short incomplete checklist of ways a reviewer or the public might evaluate a submitted hypothesis.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do you believe it is true/false? Elaborate.&lt;/li&gt;
&lt;li&gt;Is it precisely stated?&lt;/li&gt;
&lt;li&gt;Is it feasible to evaluate? Does the proposed evaluation actually evaluate the hypothesis?&lt;/li&gt;
&lt;li&gt;Is it ethical?&lt;/li&gt;
&lt;li&gt;Is it worthwhile to pursue?
&lt;ul&gt;
&lt;li&gt;Cost&lt;/li&gt;
&lt;li&gt;Impact&lt;/li&gt;
&lt;li&gt;Downstream research unlocked&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Is it interesting / surprising?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The notion of &amp;ldquo;likely to be surprising&amp;rdquo; is interesting, and is an important one for a strong hypothesis.&lt;/p&gt;
&lt;h4 id=&#34;implementation-details&#34;&gt;Implementation details&lt;/h4&gt;
&lt;p&gt;As I mused in the introduction, &amp;ldquo;Hypothesis OpenReview&amp;rdquo; may be a more fitting name for the idea than &amp;ldquo;Hypothesis Arxiv&amp;rdquo;, and a journal or conference named &amp;ldquo;Machine Learning Hypotheses&amp;rdquo; is an appealing way to frame the venue for me. Perhaps OpenReview is already well suited for this idea. Instead of developing a new website, one possible implementation is to organize a new &lt;em&gt;conference&lt;/em&gt;, with submissions collected and discussed on OpenReview, where the gimmick of the conference is as discussed in this snippet: the authors need not perform the experiments they advocate for.&lt;/p&gt;
&lt;p&gt;How do we get people to (A) submit hypotheses, (B) review hypotheses, and (C) do both in a scholarly manner? The first step is to circulate this idea so we can discuss and improve upon it. If we can gather support (either for the idea as is, or a future modified version of it), from well respected researchers, their support could be instrumental in getting a &amp;ldquo;hypothesis journal&amp;rdquo; off the ground.&lt;/p&gt;
&lt;h4 id=&#34;similar-ideas&#34;&gt;Similar ideas&lt;/h4&gt;
&lt;p&gt;I&amp;rsquo;m aware of three ideas most similar to this one that have been tried in the past.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Grants&lt;/li&gt;
&lt;li&gt;Preregistration&lt;/li&gt;
&lt;li&gt;Medical Hypotheses&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The &lt;em&gt;grant application process&lt;/em&gt; is similar in many ways to the submission of a hypothesis paper. We can probably learn quite a bit from this process to inform how we implement the hypothesis journal idea. The key difference between our idea and a grant application is that there is not financing attached to submission of a hypothesis in our idea, and the person submitting a hypothesis need not be the same person who eventually evaluates it.&lt;/p&gt;
&lt;p&gt;Certain fields have a practice of pre-registration. In this practice, researchers publicly commit to a research plan before beginning the research. Wikipedia suggests preregistration can reduce p-hacking, publication bias, data dredging, inappropriate post hoc analysis, and HARKing. A hypothesis journal can have many similar benefits as preregistration. A key difference between submitting a hypothesis and pre-registering a research plan is that submitting a hypothesis does not commit you to performing the research, and in fact it may be appropriate for someone else (or no one at all) to perform the hypothesis evaluation, rather than its author.&lt;/p&gt;
&lt;p&gt;Finally there is one journal &lt;em&gt;Medical Hypotheses&lt;/em&gt; that has a similar motivation (albeit less similar than the journal&amp;rsquo;s name suggests) to our hypothesis journal idea. &lt;em&gt;Medical Hypotheses&lt;/em&gt; was designed to allow discussion of unconventional ideas, which is a different goal than we are pursuing. Like with our idea, the experiments to validate the ideas need not be run yet. This journal published controversial papers on AIDS denialism, and for most of its existence largely forwent peer review.
We can probably learn quite a bit from the history of &lt;em&gt;Medical Hypotheses&lt;/em&gt;. One lesson is that peer review and the publication of hypotheses are orthogonal; I suggest we keep peer review, while still encouraging the submission of hypotheses before they have been evaluated.&lt;/p&gt;
&lt;h4 id=&#34;concerns&#34;&gt;Concerns&lt;/h4&gt;
&lt;p&gt;In my brainstorming, I anticipate a handful of potential concerns about the idea.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Flag-planting&lt;/li&gt;
&lt;li&gt;Scooping&lt;/li&gt;
&lt;li&gt;Prestige / Motivation for participation&lt;/li&gt;
&lt;li&gt;Collapsing of the idea space (need divergence and convergence; don&amp;rsquo;t want to be left with an overabundance of convergence and insufficient divergence)&lt;/li&gt;
&lt;li&gt;Ideas are a dime a dozen&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Personally, I am not so concerned about &lt;em&gt;flag-planting&lt;/em&gt;. The primary purpose of the idea is to share hypotheses and inspire others to evaluate or build off of them. Flag-planting is a problem if it involves people claiming overly broad ideas prematurely so that they get future credit once the idea is more carefully analyzed and the specific instantiation of the idea that is most important comes to light.
Credit is a finicky thing, but from my perspective it is rare in modern science that full credit is attributed to a single individual or single group; the story is always more complicated. If someone proposes an overly broad hypothesis, effectively flag-planting, then perhaps they will in turn receive a portion of the credit for the specific important idea that develops from it. I do not find this objectionable. I would be curious to discuss this with you if you find flag-planting a larger concern than I am making it out to be with this idea.&lt;/p&gt;
&lt;p&gt;A fear of &lt;em&gt;scooping&lt;/em&gt; could certainly prevent people from submitting ideas to the &amp;ldquo;Machine Learning Hypothesis&amp;rdquo; journal. However, I expect that most researchers have a long line of hypotheses that they will never have the time to evaluate. So, my hope is that researchers who fear scooping could choose to keep the hypotheses they are actively working on a secret, while still opening up and sharing the many others that they possess.
For many researchers, even publishing the hypotheses that they are actively working on will be worthwhile. This allows them to get (partial) credit for the idea earlier (in effect preventing a form of scooping) than if they had to finish the research paper before submitting the idea, and it allows for earlier feedback on their research which usually leads to higher quality research overall.&lt;/p&gt;
&lt;p&gt;Next comes the issue of &lt;em&gt;motivating&lt;/em&gt; people to submit to the conference. I think that we could actually make this conference the most interesting and most fun of the machine learning conferences. Discussing half-baked ideas with researchers is always enjoyable, and I am optimistic a significant fraction of the ML research community could enjoy both submitting to this journal, and reviewing for it, because doing both is a great exercise in research creativity. Prestige and funding are other motivators for researchers; I do not think a hypothesis journal could ever be as prestigious as typical top ML conferences, but I do think that with the backing of strong players and institutions in the research community, sufficient prestige could be attached to strong submissions to the conference/journal.&lt;/p&gt;
&lt;p&gt;The next concern is about &lt;em&gt;collapsing of the idea space&lt;/em&gt;. In order for a group to come up with the best possible ideas, there needs to be space for the group&amp;rsquo;s thinking to diverge, as well as space for discussion leading to some amount of convergence on good ideas. The hypothesis journal idea increases the amount of convergence. Some might argue we actually need more divergence in our thinking. I would be interested to discuss this with you if you have this concern.&lt;/p&gt;
&lt;p&gt;Finally, a possible concern is that hypotheses without experiments are not on their own valuable, e.g. that &amp;ldquo;ideas are a dime a dozen&amp;rdquo;. To address this concern, I think we merely need to raise the bar about what constitutes a good hypothesis. We&amp;rsquo;re not looking for just any old idea, but rather ones that will advance the science of machine learning, backed up by the evidence the machine learning community has collected, and likely to be impactful on future science. Coming up with a good hypothesis is not easy, but a popular hypothesis journal could be an effective tool for improving our collective ability to do so.&lt;/p&gt;
&lt;p&gt;If you share these concerns of have additional ones not discussed here, please get in touch. I&amp;rsquo;d love to discuss.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I describe the &amp;ldquo;hypothesis arxiv&amp;rdquo; idea using the language of empirical science, but in principle the idea could be applied to entirely theoretical fields as well. In that setting, the idea would be to make space for unproven conjectures to be shared more freely. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;And if a hypothesis submitted to the hypothesis arxiv by one group is being evaluated by another group, then it would make sense to me to include the first group closely in the evaluation process. In this way, the &amp;ldquo;hypothesis arxiv&amp;rdquo; may open up LLM research even more than described in the main text. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Potential Improvements to Spaced Repetition</title>
      <link>https://davidbieber.com/snippets/2021-11-02-improvements-to-spaced-repetition/</link>
      <pubDate>Tue, 02 Nov 2021 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-11-02-improvements-to-spaced-repetition/</guid>
      
      <description>&lt;p&gt;Spaced repetition is not super widespread. It&amp;rsquo;s popular among med school students and language learners, but frequently people find the benefits outweighed by the costs, the friction too high, and they stop.&lt;/p&gt;
&lt;p&gt;I believe the following are the most pressing issues to solve for spaced repetition to allow for wider adoption:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Card creation: Zero friction card creation&lt;/li&gt;
&lt;li&gt;Card creation: Good cards by default&lt;/li&gt;
&lt;li&gt;Card maintenance: Eject bad cards quickly&lt;/li&gt;
&lt;li&gt;Schedule flexibility: Allow people to study more&lt;/li&gt;
&lt;li&gt;Schedule flexibility: Allow people to study less&lt;/li&gt;
&lt;li&gt;Review friction: Bring the reviews to the users&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If we solve these six issues, I think that could open up spaced repetition to a much wider audience. In this snippet I&amp;rsquo;ll elaborate briefly on all six ideas. I then also want to share one additional idea, which I think is the most important issue to solve for improving spaced repetition for existing users:&lt;/p&gt;
&lt;ol start=&#34;7&#34;&gt;
&lt;li&gt;SRS that understands card connections&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let&amp;rsquo;s dive right in.&lt;/p&gt;
&lt;h4 id=&#34;1-card-creation-zero-friction-card-creation&#34;&gt;1. Card creation: Zero friction card creation&lt;/h4&gt;
&lt;p&gt;We need to make it so easy to create new flashcards that it becomes as common and quick as making a Google search.&lt;/p&gt;
&lt;p&gt;People tend to use spaced repetition systems in one of two ways. They either create cards themselves, one by one, or they import existing decks of flash cards made by someone else. My hunch is that the latter use case is currently more common, because for most people creating a deck of cards themself is too much friction.&lt;/p&gt;
&lt;p&gt;Deck reuse can be a good thing; if there is a high quality deck for precisely what you want to learn, it can save you a lot of time just using that deck rather than making a new one. I think we need to change this, though. We need to reduce the friction to creating new cards substantially. This is because so much of what people learn is specific to their own experiences &amp;ndash; the articles they read, the vocabulary that interests them, the specific things they find important to remember.&lt;/p&gt;
&lt;p&gt;Machine learning and automation will each play critical roles here. Here are some ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create cards just by highlighting the important fact you want to remember. 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-07-29-note-taking-flow/&#34;&gt;I do this today using Browserflow&lt;/a&gt;. If I highlight a phrase and press &amp;ldquo;c&amp;rdquo;, a flashcard is created with the sentence containing the highlight, with the highlighted part masked out.&lt;/li&gt;
&lt;li&gt;Machine learning can be used to improve the quality of the generated cards, for example by ensuring the card has all the necessary context from the website to make sense on its own.&lt;/li&gt;
&lt;li&gt;Create cards just by browsing the web. Using machine learning, we can generate flashcards from the websites you visit and the search queries you make. I believe we can design a user interface that requires minimal effort from the user and still generates high quality cards that the user cares about and wants to study.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;2-card-creation-good-cards-by-default&#34;&gt;2. Card creation: Good cards by default&lt;/h4&gt;
&lt;p&gt;When people create flashcards for themselves, they often create bad cards. A good card is a card that is small, meaningful, and connected. It&amp;rsquo;s quick to recall or quick to fail, but either way doesn&amp;rsquo;t bog down the person studying. When people have cards that are too big, they get bogged down, review sessions become a chore, and people drop the habit of spaced repetition.&lt;/p&gt;
&lt;p&gt;One way to ensure good cards by default is to build good properties directly into the low friction card generators. Fill-in-the-blank cards generated by the highlighting method mentioned above are usually good by default. Image occlusion cards that blank out a small piece of text make good cards, and a tool can steer people toward making these good kinds of cards.&lt;/p&gt;
&lt;p&gt;A common failure mode is to make open ended cards or cards with long answers. My suspicion is that these cards lower the effectiveness of spaced repetition and lead to people dropping the habit.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also important that users know what makes a good card. For this, they can read Andy Matuschak&amp;rsquo;s 
&lt;a href=&#34;https://andymatuschak.org/prompts/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;How to Write Good Prompts&lt;/a&gt;. Education isn&amp;rsquo;t the full story though. We need our tools to be proactive in guiding people to make good cards and recognizing when they have or have not done so.&lt;/p&gt;
&lt;h4 id=&#34;3-card-maintenance-eject-bad-cards-quickly&#34;&gt;3. Card maintenance: Eject bad cards quickly&lt;/h4&gt;
&lt;p&gt;A common habit of experienced spaced repetition users is to remove cards that take too long from their deck. The most popular spaced repetition tools allow users to do this, but they should go further. They should proactively encourage users to eject bad cards.&lt;/p&gt;
&lt;p&gt;In fact, I think these system should go even further than that. They should eject detected bad cards by default, giving users an opportunity to preserve these cards only if they explicitly choose to do so.&lt;/p&gt;
&lt;p&gt;How can a spaced repetition system detect bad cards? The main way is by looking at the time spent reviewing it. Other clues come from the length of the answer, and other properties of the answer. Getting this exactly right is a challenging problem, but I&amp;rsquo;m confident that we have the tool set (e.g. natural language processing, Quizlet user data) to make significant progress on this. Even a rough heuristic approach to detecting bad cards, coupled with active encouragement for people to eject bad cards, I think would go a long way.&lt;/p&gt;
&lt;h4 id=&#34;4-schedule-flexibility-allow-people-to-study-more&#34;&gt;4. Schedule flexibility: Allow people to study more&lt;/h4&gt;
&lt;p&gt;This and the next item go hand in hand; spaced repetition scheduling algorithms need to admit significantly greater flexibility than they do today. There isn&amp;rsquo;t a single best time to review some item. There is usually a wide and fuzzy range of good times to review something. And extra review, while it might mess with the scheduling, is almost always a good thing.&lt;/p&gt;
&lt;p&gt;If someone is motivated to study extra, spaced repetition systems should encourage it. The scheduling algorithm should adapt.&lt;/p&gt;
&lt;p&gt;This is especially important because people&amp;rsquo;s levels of motivations change from day to day. And most people can&amp;rsquo;t do review sessions everyday anyway (see next item, studying less). We should build tools that work for people, not ones that constrain people. In the context of spaced repetition, this means we want to amplify people&amp;rsquo;s motivations.&lt;/p&gt;
&lt;p&gt;If someone is really into a particular topic on a particular day, their spaced repetition system should help them study that topic to their heart&amp;rsquo;s content. In today&amp;rsquo;s spaced repetition systems that might just mean studying the cards related to that topic over and over. In tomorrow&amp;rsquo;s spaced repetition system, this might be giving them new related content to learn (but, while fun and futuristic, that&amp;rsquo;s a less pressing enhancement to make than the six I&amp;rsquo;ve listed here).&lt;/p&gt;
&lt;h4 id=&#34;5-schedule-flexibility-allow-people-to-study-less&#34;&gt;5. Schedule flexibility: Allow people to study less&lt;/h4&gt;
&lt;p&gt;As mentioned, people&amp;rsquo;s motivations and availability to study fluctuates. Spaced repetition systems should never make their users feel bad about not studying. This demands both UI changes and algorithmic changes.&lt;/p&gt;
&lt;p&gt;First, missing a single day of studying should not feel like a giant impenetrable wall of a backlog has been erected. The reviews for most of the cards you missed can be smoothed out over several days or weeks anyway, with minimal degradation to your memory quality. The UI should not make you feel like you&amp;rsquo;ve built up a full day&amp;rsquo;s backlog when you miss a single day of review.&lt;/p&gt;
&lt;p&gt;And this shouldn&amp;rsquo;t just be a cosmetic change either; missing review sessions should be a normal thing. Week-long or month-long (or longer!) vacations should be a normal scenario. Obviously, the more time you spend studying the more you can learn and the better you can remember things, but daily studying is not a strict requirement for getting the benefits of spaced repetition. Those benefits scale gracefully up or down with the amount of time you&amp;rsquo;re willing to put in, and the software that implements spaced repetition should expose this smooth scaling property.&lt;/p&gt;
&lt;p&gt;Spaced repetition systems should handle people taking vacations gracefully. One way to achieve this is by using ranges rather than specific dates when scheduling card reviews. The acceptable range of times for studying a card should grow considerably as you become more familiar with that card.&lt;/p&gt;
&lt;p&gt;If a user does choose to study less that is needed to learn all the material they want to learn, then another possible response is to thin out the material. With the user&amp;rsquo;s input, remove some material such that the amount of material being studied is in line with the amount of study time being put in. This relates directly to idea 7., which I believe can increase the study material to study time ratio significantly for existing spaced repetition users.&lt;/p&gt;
&lt;h4 id=&#34;6-review-friction-bring-the-reviews-to-the-users&#34;&gt;6. Review friction: Bring the reviews to the users&lt;/h4&gt;
&lt;p&gt;The final significant way we can reduce the friction to using spaced repetition systems is to move the review system to the person&amp;rsquo;s primary inbox. That might be their email, or their text messages, or somwehere else &amp;ndash; wherever it is they maintain inbox zero.&lt;/p&gt;
&lt;p&gt;This is the same philosophy I use with Bieber Bot &amp;ndash; if Bieber Bot sent me messages to a system I never checked, or one with hundreds of backlogged messages, it wouldn&amp;rsquo;t be useful to me. Instead, he sends messages to FB Messenger where I already read every message. So I don&amp;rsquo;t miss messages from Bieber Bot and his messages have continued to be useful for years.&lt;/p&gt;
&lt;p&gt;When people have to switch apps to e.g. Anki, it is easier for them to fall out of the habit of doing spaced repetition. If instead, spaced repetition were built directly into an app they were already using constantly and already responding to all notifications for, it would be easy to develop into a habit.&lt;/p&gt;
&lt;p&gt;For me, this place is Roam Research. I take notes in Roam throughout the day, and so it&amp;rsquo;s natural for me to do a review session in Roam. No extra app needed.&lt;/p&gt;
&lt;p&gt;For most people, I think baking spaced repetition directly into an email client probably makes the most sense. Who knows though? Maybe TikTok spaced repetition is even better :).&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Together these six issues can move the needle significantly in reducing friction to using spaced repetition. I expect just solving these six could for many people bring spaced repetition across the chasm from &amp;ldquo;not practical&amp;rdquo; to &amp;ldquo;practical&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;There are still further major improvements that can be made to spaced repetition beyond these though. Here is the one I think is most important, which could potentially save a significant amount of time or increase people&amp;rsquo;s capacity to review material substantially:&lt;/p&gt;
&lt;h4 id=&#34;7-srs-that-understands-card-connections&#34;&gt;7. SRS that understands card connections&lt;/h4&gt;
&lt;p&gt;We need a smarter scheduling algorithm that understands the connections between cards. If you review many related cards over many years, those cards start to become related in your head. Reviewing one will also jog your memory about others. However, today&amp;rsquo;s spaced repetition systems schedule each card independently. Getting one card right should push back the schedule not only for that card, but also for related cards.&lt;/p&gt;
&lt;p&gt;Consider a flashcard about conjugating a verb. This card tests two things: (1) do you know the vocab, and (2) do you know how to do the conjugation. Other cards might test the same vocab in a different way, and still other cards might test the same conjugation rule but on a different verb. Getting the card right is (partial) evidence that you will also get other cards testing the same underlying skills correct. We need a spaced repetition scheduling algorithm that can take advantage of these connections.&lt;/p&gt;
&lt;p&gt;Another example is learning 2-digit addition. When you&amp;rsquo;re first learning the skill, you might have hundreds of distinct cards with 2-digit addition questions. Years later, it might be good to occasionally review 2-digit addition to make sure you&amp;rsquo;ve still got the skill, but you only need to do a small number of cards to convince yourself and the system that you&amp;rsquo;ve still mastered the skill. The other cards can get pushed back each time you demonstrate their review isn&amp;rsquo;t going to be helpful to you since you&amp;rsquo;ve retained mastery of the skill.&lt;/p&gt;
&lt;p&gt;With a scheduling algorithm that understands these connections between cards, I believe that overall reviews can be made less frequent than today&amp;rsquo;s algorithms allow for. Over the long term, the total review time for vocabulary and conjugation cards might be reduced by a substantial factor. The total review time for mathematical skill cards might be reduced even more. This can free up time for spaced repetition users to either study for less time, or to study more material. This would be a significant win for the technique.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>DDoV for DAOs</title>
      <link>https://davidbieber.com/snippets/2021-11-02-ddov-for-daos/</link>
      <pubDate>Tue, 02 Nov 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-11-02-ddov-for-daos/</guid>
      
      <description>&lt;p&gt;I wrote up the idea for 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-01-11-democratic-delegation-optional-voting/&#34;&gt;Democratic Delegation-optional Voting (DDoV)&lt;/a&gt; back in January. This was before I learned about DAOs (decentralized autonomous organizations). I think the idea is even more relevant in the context of DAOs than it was originally, and I&amp;rsquo;m intrigued to revisit it now that I am learning about DAOs.&lt;/p&gt;
&lt;p&gt;The core of the idea is a governance structure that supports ad hoc delegation of votes. Since there are potentially many things to vote on, but not everybody is invested enough or has enough time to learn about and vote on all of them, delegation is important. Without it, there are some problems&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;In DDoV, there&amp;rsquo;s no &lt;em&gt;need&lt;/em&gt; to delegate your vote; you can always cast your vote yourself. Anyone can delegate their vote(s), and anyone who wants to act as a delegate can have votes delegated to them. This setup admits much more flexibility that traditional elected representatives, while still preserving many of the benefits of elected representatives.&lt;/p&gt;
&lt;p&gt;The flexibility arises because any individual or group can, hopefully without stigma or repercussion, redelegate their votes at any time, or even reclaim them and cast them manually. A benefit that is preserved is the possibility of centralized decision making. A small number of people &lt;em&gt;can&lt;/em&gt;, at the behest of the stakeholders, hold majority voting power for particular issues. In these scenarios, a concentrated number of voices can discuss issues and reach compromises. If any compromise is objectionable to the stakeholders, they are at liberty to redelegate their votes, but the possibility for mental offloading to representatives remains.&lt;/p&gt;
&lt;p&gt;What is being offloaded to representatives? It&amp;rsquo;s the hard work of understanding the issues being voted on, deciding on the best course of action, convincing others of their opinions, and casting their votes.&lt;/p&gt;
&lt;p&gt;Searching around a bit for existing DAOs, I see that voting delegation has been proposed and tried now. I haven&amp;rsquo;t seen any DAO fully implement the DDoV proposal though, allowing for delegating and redelegating. Specifically, here is what I would want to see minimally in an implementation:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;For each election, every member of an organization receives tokens that represent their voting power. For each token you hold, you can place a vote.&lt;/li&gt;
&lt;li&gt;Any member can mark themselves as a delegate; this means they can receive tokens from other members.&lt;/li&gt;
&lt;li&gt;Any member can give a token they hold to a delegate. This includes delegates forwarding tokens they receive to other delegates.&lt;/li&gt;
&lt;li&gt;A member can recall their tokens back from whoever holds them at any time.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;On top of these basic primitives, the following would make the system more useful:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Members can set up rules to automatically give out tokens conditioned on the particular issue being voted on. For example, for all education issues, I might automatically send my voting tokens to someone I trust on education.&lt;/li&gt;
&lt;li&gt;Votes by delegates are made public and locked in before the voting period ends. After this lock-in point, members can still recall their own tokens and modify their own votes. Only delegate-votes cannot be changed (but they can be recalled by the original owner of the voting token.)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Point 1 here allows for effective representatives to emerge, even if in practice they are ephemeral and can have their power revoked by the people at any time.
Point 2 here allows the members to hole ultimate control over their own votes if for some reason their representative behaves in a way contrary to their own views.&lt;/p&gt;
&lt;p&gt;I am not yet caught up to date with the implementations that DAOs have tried in practice. This is something I&amp;rsquo;m interested to learn more about, and then perhaps DDoV (or some future version of it) will be an effective voting strategy for a future DAO.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;What are the problems that arise with naive voting?
&lt;br/&gt;
(1) You can only hold votes on a small number of things before overwhelming the governing body. If you have too many things to vote on, people will be unable to adequately inform themselves about all items.
&lt;br/&gt;
(2) Everybody needs to learn about and vote on every item.
&lt;br/&gt;
(3) If only a small fraction of voters are voting on typical items, a small number of people could easily sneak a vote past the majority that the majority would disagree with. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Machine Learning and Automation Ideas for Note-taking</title>
      <link>https://davidbieber.com/snippets/2021-10-28-ml-and-automation-for-note-taking/</link>
      <pubDate>Thu, 28 Oct 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-10-28-ml-and-automation-for-note-taking/</guid>
      
      <description>&lt;p&gt;Let&amp;rsquo;s consider machine learning first, and then automation. For each we brainstorm the potential value for note-taking.&lt;/p&gt;
&lt;h3 id=&#34;the-value-of-markmachine-learningmark-for-note-taking&#34;&gt;The Value of &lt;mark&gt;Machine Learning&lt;/mark&gt; for Note-Taking&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Automatic &lt;strong&gt;transcription&lt;/strong&gt; of audio notes
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Speaker identification&lt;/strong&gt; during meetings or conversations&lt;/li&gt;
&lt;li&gt;Resurfacing of action items, surfacing relevant information, and performing actions (e.g running a google search or sending a message) in response to audio cues during meetings or conversations&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Automatic &lt;strong&gt;categorization&lt;/strong&gt; of notes&lt;/li&gt;
&lt;li&gt;Automatic &lt;strong&gt;categorization of spaced repetition&lt;/strong&gt; flash cards&lt;/li&gt;
&lt;li&gt;Automatic &lt;strong&gt;context-filling&lt;/strong&gt; of spaced repetition flash cards
&lt;ul&gt;
&lt;li&gt;e.g. highlight a phrase to create a flash card; the necessary context is pulled in from surrounding paragraphs to make a coherent standalone flash card.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Automatic &lt;strong&gt;connections&lt;/strong&gt; and graph construction:
&lt;ul&gt;
&lt;li&gt;Textual elements:
&lt;ul&gt;
&lt;li&gt;Entity extraction from notes (&amp;ldquo;implicit nodes&amp;rdquo;, e.g. &amp;ldquo;Bank of America&amp;rdquo;)&lt;/li&gt;
&lt;li&gt;Attribute extraction from notes (e.g. &amp;ldquo;incredible presentation by Pierre-Antoine&amp;rdquo; gets tagged as incredible or wow (the canonical form).)&lt;/li&gt;
&lt;li&gt;Relationship extraction (e.g. &amp;ldquo;Diamond Age by Neal Stephenson&amp;rdquo; -&amp;gt; creates an &amp;ldquo;author of&amp;rdquo; relationship)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Background knowledge elements:
&lt;ul&gt;
&lt;li&gt;e.g. knowing that Diamond Age is a book&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Writing prompt generator / &lt;strong&gt;Writing assistant&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Overlap detection&lt;/strong&gt; between people&amp;rsquo;s graphs
&lt;ul&gt;
&lt;li&gt;The Go Note Go &amp;ldquo;clink&amp;rdquo; scenario&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Autocomplete&lt;/strong&gt; (e.g. gmail tab completion)&lt;/li&gt;
&lt;li&gt;Improved &lt;strong&gt;spaced repetition algorithms&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Mistake detection / &lt;strong&gt;fact checking&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Summarization&lt;/strong&gt; of notes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Highlight extraction&lt;/strong&gt; from notes&lt;/li&gt;
&lt;li&gt;Suggesting &lt;strong&gt;new ideas&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Suggesting &lt;strong&gt;new online resources&lt;/strong&gt; to read / explore
&lt;ul&gt;
&lt;li&gt;Incl. articles, papers, YouTube videos, Suggesting &lt;strong&gt;people to reach out to&lt;/strong&gt; (e.g. because of their blog or Twitter or other things they&amp;rsquo;re written)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Semantic search&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conversational chat bots&lt;/strong&gt; for exploring the knowledge in a notebase&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;the-value-of-markautomationmark-for-note-taking&#34;&gt;The Value of &lt;mark&gt;Automation&lt;/mark&gt; for Note-Taking&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Share notes&lt;/strong&gt; with people via their preferred messaging platform&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Snooze notes&lt;/strong&gt; and ideas so you review them later&lt;/li&gt;
&lt;li&gt;Set pomodoros, alarms, and reminders to &lt;strong&gt;stay focused&lt;/strong&gt; and &lt;strong&gt;stay on task&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Note-taking &lt;strong&gt;via highlights&lt;/strong&gt; (e.g. with Browserflow)&lt;/li&gt;
&lt;li&gt;Note-taking &lt;strong&gt;via screenshots&lt;/strong&gt; (e.g. from YouTube)&lt;/li&gt;
&lt;li&gt;Automatic creation of &lt;strong&gt;spaced repetition from highlights&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bulk refactors&lt;/strong&gt; of note-taking&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pulling in context&lt;/strong&gt; from other sources (e.g. Warmly pulls LinkedIn info into Calendar, notes could pull info from wikipedia)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sync notes&lt;/strong&gt; between other sources and your notebase
&lt;ul&gt;
&lt;li&gt;Other people&amp;rsquo;s notes&lt;/li&gt;
&lt;li&gt;Your email client, calendar, TODO app, spaced repetition app, GitHub issues, other messaging services, etc&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Publishing&lt;/strong&gt; of notes to a webpage (either publicly or privately), or to social media&lt;/li&gt;
&lt;li&gt;New &lt;strong&gt;data entry&lt;/strong&gt; mechanisms: &lt;strong&gt;Go Note Go&lt;/strong&gt;, terminal, email, text, browsing history, location history, terminal history, IoT devices, etc&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spaced repetition&lt;/strong&gt; for studying&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inactivity reminders&lt;/strong&gt; (e.g. &amp;ldquo;it&amp;rsquo;s been three months since you&amp;rsquo;ve done a music activity&amp;rdquo;, or &amp;ldquo;it&amp;rsquo;s been over 6 months since you&amp;rsquo;ve spoken with David Dohan&amp;rdquo;, or &amp;ldquo;it&amp;rsquo;s been over a year since you&amp;rsquo;ve written about microbiology.&amp;quot;)&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Go Note Go Hardware</title>
      <link>https://davidbieber.com/snippets/2021-10-26-go-note-go-hardware/</link>
      <pubDate>Tue, 26 Oct 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-10-26-go-note-go-hardware/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;ve put together a hardware guide so you can build your own Go Note Go. I&amp;rsquo;ll keep a version of this in the 
&lt;a href=&#34;https://github.com/dbieber/GoNoteGo&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Go Note Go GitHub repo&lt;/a&gt; too. This one will likely fall out of date, but I&amp;rsquo;ll try to keep the one in the GitHub repo updated.&lt;/p&gt;
&lt;h3 id=&#34;raspberry-pi-400&#34;&gt;Raspberry Pi 400&lt;/h3&gt;
&lt;p&gt;Link: &lt;a href=&#34;https://www.raspberrypi.com/products/raspberry-pi-400-unit/&#34;&gt;https://www.raspberrypi.com/products/raspberry-pi-400-unit/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Details: I use the US keyboard. You can purchase from e.g. PiShop. I recommend ordering the following as a bundle:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Raspberry Pi 400 unit ($70)&lt;/li&gt;
&lt;li&gt;Class 10 microSD Card With Raspbian - 16GB&lt;/li&gt;
&lt;li&gt;USB-C Power Supply, 5.1V 3.0A, Black, UL Listed&lt;/li&gt;
&lt;li&gt;Micro-HDMI to HDMI cable for Pi 4, 3ft, Black&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cost: $91&lt;/p&gt;
&lt;h3 id=&#34;voice-bonnet&#34;&gt;Voice bonnet&lt;/h3&gt;
&lt;p&gt;Link: &lt;a href=&#34;https://www.adafruit.com/product/4757&#34;&gt;https://www.adafruit.com/product/4757&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Notes: I&amp;rsquo;ve actually had some issues with these. The microphone records a high pitched noise and the audio output is quiet and muffled. I will suggest an (untested) alternative speaker and mic below.&lt;/p&gt;
&lt;p&gt;Cost: $20&lt;/p&gt;
&lt;h3 id=&#34;2x20-connector&#34;&gt;2x20 Connector&lt;/h3&gt;
&lt;p&gt;Link: &lt;a href=&#34;https://www.adafruit.com/product/4079&#34;&gt;https://www.adafruit.com/product/4079&lt;/a&gt; OR &lt;a href=&#34;https://www.adafruit.com/product/2223&#34;&gt;https://www.adafruit.com/product/2223&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Recommendation: Get the 
&lt;a href=&#34;https://www.adafruit.com/product/2223&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;long pins one&lt;/a&gt;. The 
&lt;a href=&#34;https://www.adafruit.com/product/4079&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;short pins one&lt;/a&gt; is sleeker but the long pins might become necessary for connecting the button. TBD.&lt;/p&gt;
&lt;p&gt;Notes: Use this to attach the voice bonnet to the Pi.&lt;/p&gt;
&lt;p&gt;Cost: $3&lt;/p&gt;
&lt;h3 id=&#34;10000-mah-battery&#34;&gt;10000 mAh battery&lt;/h3&gt;
&lt;p&gt;Link: &lt;a href=&#34;https://www.amazon.com/gp/product/B07JYYRT7T&#34;&gt;https://www.amazon.com/gp/product/B07JYYRT7T&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Notes: There are lots of options for the battery. This one works just fine. Could choose one with more storage for longer battery life if desired, but might get clunky.&lt;/p&gt;
&lt;p&gt;Cost: $19 (currently $14)&lt;/p&gt;
&lt;h3 id=&#34;velcro&#34;&gt;Velcro&lt;/h3&gt;
&lt;p&gt;Link: &lt;a href=&#34;https://www.amazon.com/gp/product/B08P3MXLLD&#34;&gt;https://www.amazon.com/gp/product/B08P3MXLLD&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Notes: I use this Velcro to mount the keyboard to the passenger side of the car, and to mount the battery to the back of the keyboard. When applying the sticky side to a car dashboard, allow to dry overnight.&lt;/p&gt;
&lt;p&gt;Cost: $7&lt;/p&gt;
&lt;h3 id=&#34;usb-cables&#34;&gt;USB Cables&lt;/h3&gt;
&lt;p&gt;Links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;3 ft USB - USB C cable: &lt;a href=&#34;https://www.amazon.com/gp/product/B089DM4KDW&#34;&gt;https://www.amazon.com/gp/product/B089DM4KDW&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;6 in USB - USB C cable: &lt;a href=&#34;https://www.amazon.com/gp/product/B012V56D2A&#34;&gt;https://www.amazon.com/gp/product/B012V56D2A&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cost: $13 ($6.99 for 3 ft and $5.99 for 6 in)&lt;/p&gt;
&lt;h3 id=&#34;the-beautiful-red-button&#34;&gt;The Beautiful Red Button&lt;/h3&gt;
&lt;p&gt;Link: &lt;a href=&#34;https://www.amazon.com/gp/product/B00T6RCGNC&#34;&gt;https://www.amazon.com/gp/product/B00T6RCGNC&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Cost: $9&lt;/p&gt;
&lt;h3 id=&#34;alternative-mic-and-speaker&#34;&gt;Alternative Mic and Speaker&lt;/h3&gt;
&lt;p&gt;Links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Microphone: &lt;a href=&#34;https://www.adafruit.com/product/3367&#34;&gt;https://www.adafruit.com/product/3367&lt;/a&gt; ($6)&lt;/li&gt;
&lt;li&gt;Speaker: &lt;a href=&#34;https://www.adafruit.com/product/3369&#34;&gt;https://www.adafruit.com/product/3369&lt;/a&gt; ($13)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Notes: I haven&amp;rsquo;t gotten these set up with Go Note Go yet, but am considering them as an alternative to the Adafruit Voice Bonnet. I really like the LEDs on the voice bonnet though, so TBD.&lt;/p&gt;
&lt;p&gt;Cost: $19&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;other-tools&#34;&gt;Other tools:&lt;/h2&gt;
&lt;h3 id=&#34;external-monitor-and-a-usb-mouse&#34;&gt;External monitor and a USB Mouse.&lt;/h3&gt;
&lt;p&gt;These will be useful for configuring and debugging Go Note Go, e.g. setting up WiFi and configuring your note-taking system.&lt;/p&gt;
&lt;h3 id=&#34;wire-wire-stripper&#34;&gt;Wire, Wire Stripper&lt;/h3&gt;
&lt;p&gt;If you use The Beautiful Red Button you&amp;rsquo;ll need wire and wire strippers. For wire I used 18 gauge lamp wire I got from Home Depot.&lt;/p&gt;
&lt;p&gt;Possible link: &lt;a href=&#34;https://www.lowes.com/pd/Southwire-25-Ft-18-2-Black-Stranded-Lamp-Cord/5001050863&#34;&gt;https://www.lowes.com/pd/Southwire-25-Ft-18-2-Black-Stranded-Lamp-Cord/5001050863&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Wire stripper link: &lt;a href=&#34;https://www.amazon.com/Mr-Stripper-Stripping-Crimping-Electrical/dp/B086V5M1B4&#34;&gt;https://www.amazon.com/Mr-Stripper-Stripping-Crimping-Electrical/dp/B086V5M1B4&lt;/a&gt; (Chose this one arbitrarily; I got mine at Home Depot)&lt;/p&gt;
&lt;p&gt;Notes: I don&amp;rsquo;t know if this is the best choice for wire; a higher gauge might be better.&lt;/p&gt;
&lt;h3 id=&#34;solder-soldering-iron&#34;&gt;Solder? Soldering iron?&lt;/h3&gt;
&lt;p&gt;I haven&amp;rsquo;t had to use solder yet, but might need to for hooking up the button.&lt;/p&gt;
&lt;p&gt;Hot glue or heat shrink and a heat gun might be nice-to-haves too to ensure solid stable connections.&lt;/p&gt;
&lt;h3 id=&#34;possible-other-parts-for-button&#34;&gt;Possible other parts for button&lt;/h3&gt;
&lt;p&gt;These might be useful for connecting the button to the GPIO pins on the Pi:
&lt;a href=&#34;https://www.amazon.com/dp/B0774NMT1S&#34;&gt;https://www.amazon.com/dp/B0774NMT1S&lt;/a&gt;
I don&amp;rsquo;t know. In my experience these were too loose to fit nicely on the GPIO pins.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going to try these next: GenBasic 40 Piece Female to Female Jumper Wires (4 Inch) &lt;a href=&#34;https://www.amazon.com/dp/B077N58HFK&#34;&gt;https://www.amazon.com/dp/B077N58HFK&lt;/a&gt; ($5)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Health Insurance DAOs</title>
      <link>https://davidbieber.com/snippets/2021-10-20-health-insurance-daos/</link>
      <pubDate>Wed, 20 Oct 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-10-20-health-insurance-daos/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;ve recently been learning about blockchain tech including Ethereum, smart contracts, and DAOs (distributed autonomous organizations).
With this snippet I want to explore the idea of using a DAO as a substitute for traditional health insurance.
Brainstroming here, I&amp;rsquo;m also intrigued by the ideas of (1) bringing 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-01-11-democratic-delegation-optional-voting/&#34;&gt;democratic delegation-optional voting (DDoV)&lt;/a&gt; into a DAO, (2) implementing a union as a DAO for collective bargaining, and (3) using smart contracts for international agreements 
&lt;a href=&#34;https://www.nytimes.com/2021/10/20/climate/fossil-fuel-drilling-pledges.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;to avoid climate problems like this&lt;/a&gt;. These are ideas for future snippets.&lt;/p&gt;
&lt;p&gt;Health insurance at its core is about pooling people&amp;rsquo;s resources to collectively pay for their healthcare.
Typically pooling takes the form of paying premiums to an insurance company.
When healthcare is necessary, someone files a claim and &amp;ndash; subject to the claim&amp;rsquo;s approval &amp;ndash; the insurance company pays for the customer&amp;rsquo;s healthcare.
Most users of health insurance pay more in premiums than is paid out by the health insurance company, and so overall the health insurance company makes money.
But if a customer ever incurs high costs of healthcare, they don&amp;rsquo;t have to bear those costs themself; the insurance company will pay the costs.&lt;/p&gt;
&lt;p&gt;If we&amp;rsquo;re to use a DAO in place of a traditional health insurance company, the overall structure remains the same.
Customers become members of the health insurance DAO (henceforth, &amp;ldquo;HIDAO&amp;rdquo;) by regularly paying a premium to the HIDAO.
Every month in exchange for paying your premium to the HIDAO, you receive a token.
This token indicates your membership in the HIDAO, enabling you to file a claim to receive reimbursement for healthcare costs.
In the first version of the HIDAO, an existing claims adjudication company can be used to validate claims.
A smart contract would use 
&lt;a href=&#34;https://ethereum.org/en/developers/docs/oracles/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;the oracle pattern&lt;/a&gt; to interface with the adjudicators.
When the adjudicators approve a claim, the HIDAO&amp;rsquo;s smart contract automatically processes it, thereby paying the customer for their healthcare.&lt;/p&gt;
&lt;p&gt;This setup enables some interesting possibilities beyond what&amp;rsquo;s possible with traditional health insurance.&lt;/p&gt;
&lt;p&gt;First is lower costs. Since there is no centralized for-profit institution here, all excess premiums can be returned to shareholders (the customers themselves!) as dividends. The HIDAO needs to keep some reserves in order to be able to process any unexpected spike in claims or healthcare costs. Beyond this reserve level are funds that would traditionally be operating expenses or profit. Operating expenses are quite low in a DAO (the main ones for the HIDAO would be gas and adjudication costs). By returning the profits to the customers, and by keeping operating expenses low with smart contracts, the costs of health insurance can be kept low.&lt;/p&gt;
&lt;p&gt;Second is collective negotiation of rates. Traditional insurance companies negotiate rates with providers. This process can be distributed, taking advantage of the distributed governance that DAOs enable to allow participants in the DAO to collectively negotiate rates. This idea requires elaboration in a future snippet. 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-01-11-democratic-delegation-optional-voting/&#34;&gt;DDoV&lt;/a&gt; may be essential to allowing governance to continue smoothly despite potential voter apathy. We can write the smart contract with a mechanism to incentivize participants to negotiate good rates for the HIDAO, e.g. by monetarily rewarding those who negotiate favorable rates.&lt;/p&gt;
&lt;p&gt;Third is &lt;strong&gt;Collective Adjudication Overriding&lt;/strong&gt;. Insurance companies notoriously get adjudication wrong some of the time. With a HIDAO, the risk of this could be greater if we&amp;rsquo;re not careful about setting up an appeal process, because the logic of a smart contract by default cannot be overruled. However, we have the option of building into the HIDAO&amp;rsquo;s smart contracts the ability to collectively override the normal adjudication process. We can write the smart contract such that if members of the HIDAO collectively decide that a claim adjudication decision was invalid, they can collectively override that decision.&lt;/p&gt;
&lt;p&gt;Fourth is supporting investing in the HIDAO. The HIDAO could issue tokens (e.g. the tokens given to customers each month) that indicate who is to receive the dividends mentioned in the first point above. Perhaps this could improve the robustness of the HIDAO. This is something to explore more later.&lt;/p&gt;
&lt;p&gt;Fifth is &lt;strong&gt;Distributed Adjudication&lt;/strong&gt;. This is a potential way to replace the traditional adjudication company described in the core idea above. The idea here is that we can incentivize people to submit only valid claims, and we can incentivize people to do proper claims adjudication. This idea deserves further elaboration in a future snippet.&lt;/p&gt;
&lt;p&gt;Lastly I have an open question: How do you handle someone who has both traditional and HIDAO health insurance? How is double filing of claims prevented in traditional health insurance? Let&amp;rsquo;s say someone expects high healthcare costs. What&amp;rsquo;s stopping them from signing up with two health insurance companies and filing claims with both of them? Probably the terms and conditions and the law. This sounds difficult to account for in the HIDAO smart contract, which ideally need not know about people&amp;rsquo;s other real world contracts with other health insurance companies.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m optimistic about this idea. I think that if done well, it could outcompete traditional health insurance. Obviously health insurance is a complicated industry and this is just a quick brainstorming, so the idea has many iterations to go. The ultimate goal is to ensure good health outcomes for everyone, and a part of the story necessarily is bringing down healthcare costs across the board. This is just one piece of that story, but I suspect it may be an importance piece.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Snapshot of my tags</title>
      <link>https://davidbieber.com/snippets/2021-10-11-snapshot-of-tags/</link>
      <pubDate>Mon, 11 Oct 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-10-11-snapshot-of-tags/</guid>
      
      <description>&lt;p&gt;Here&amp;rsquo;s a snapshot of my 
&lt;a href=&#34;https://davidbieber.com/tags&#34;&gt;tags&lt;/a&gt;. Just putting this here so I can look back on it later.&lt;/p&gt;
&lt;p&gt;note-taking (7), roam-research (23), go-note-go (3), spaced-repetition (7), snippets (23), browserflow (10), aspirational-intent (5), attention (23), taking-silly-ideas-seriously (25), table tennis (11), tech-tips (9), virtual reality (4), automatic-video-editing (7), python (16), goals (6), peer-learning-group (7), python fire (4), javascript (5), sql (10), wisdom (2), browser-history (10), thought-experiments (6), math (5), ask-me-anywhere (2), google apps script (3), puzzles (2), education (6), and esperanto (1)&lt;/p&gt;
&lt;p&gt;No tags on this snippet. I could see this snippet messing up a semantic search in the future, unfortunately. Comprehensive lists of keywords aren&amp;rsquo;t great for search engines.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rough Note-taking Interop Requirements</title>
      <link>https://davidbieber.com/snippets/2021-10-10-note-taking-interop-requirements/</link>
      <pubDate>Sun, 10 Oct 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-10-10-note-taking-interop-requirements/</guid>
      
      <description>&lt;p&gt;Yesterday I mused about 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-10-09-note-taking-system-interop/&#34;&gt;the benefits an interoperability standard could provide&lt;/a&gt; to note-taking systems. Today, I extract rough requirements for such a standard from that musing.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Note entry&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note entry projects need to be able to insert notes into a notebase regardless of which note-taking system is storing the notebase.&lt;/p&gt;
&lt;p&gt;This is critical for projects like 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-07-29-note-taking-flow/&#34;&gt;my Browserflow note-taking flows&lt;/a&gt; (which only support Roam right now) and 
&lt;a href=&#34;https://davidbieber.com/projects/go-note-go/&#34;&gt;Go Note Go&lt;/a&gt; to be multi-vendor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;Restricted note entry&amp;rdquo;&lt;/strong&gt; allows an application like Go Note Go to insert notes into an application-specific section of the notes. In a &amp;ldquo;daily notes&amp;rdquo; oriented notebase like Roam, this is a &amp;ldquo;Go Note Go&amp;rdquo;-specific section on each daily notes page. In a page-oriented notebase, this can instead be an application specific page or namespace (e.g. &amp;ldquo;Go Note Go/*&amp;quot;) that notes can be inserted into. When using restricted note entry, an application can only insert notes into their own region of the notebase. This prevents the application from performing disruptive insertions that lower the quality of the notes outside of this region.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unrestricted note entry&lt;/strong&gt; allows an application to perform a broader set of inserts, not limited to a specific region of the notes. For a note-taking entry system that also allows browsing the notes, where a user might want to insert new notes alongside an existing note they&amp;rsquo;ve pulled up, this becomes important.&lt;/p&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Note reading&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Individual note reading&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Batch note reading:&lt;/strong&gt; When notes are just text, reading large quantities of notes at a time becomes inexpensive. Often an entire text notebase is small enough to be kept in memory or transmitted over a network.&lt;/p&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;&lt;strong&gt;Incremental export&lt;/strong&gt; is critical for real-time features, such as collaborative note-taking across systems. Also necessary for this is support for a &lt;strong&gt;note view&lt;/strong&gt; and the ability to &lt;strong&gt;subscribe&lt;/strong&gt; to updates. Consider a collaborative note-taking experience. I&amp;rsquo;m taking notes in Roam, and one of my blocks is an embed of a page from your notes in Notion. As you make edits to the page in Notion, they should appear in my notes. If I have edit access on that page, I should be able to directly edit that page in my notes too, and you should see the results reflected in Notion in real time.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For this to work, both note-taking systems could need to support the necessary parts of the standard. If instead, Notion lacked the real-time import capability, a half-baked experience of cross-system collaborative note-taking could still be possible. As edits in Notion get saved, they appear in real-time in Roam. When edits are made in Roam, Notion would only render them upon reloading the page.&lt;/p&gt;
&lt;p&gt;If a conflict is introduced to the intermediate representation, it could be handled gracefully through a CRDT. If instead a conflict is introduced on the note-taking system side of things, then that note-taking system is responsible for handling the conflict resolution as it sees fit.&lt;/p&gt;
&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;The above ideas taken together (and assumed idealized) can support the applications discussed yesterday: e.g. note entry systems like Go Note Go, advancements in spaced repetition, multiplayer spaced repetition, multiplayer note-taking, summarization features, highlight extraction features. What they don&amp;rsquo;t support is the development of UI widgets that can be developed once and deployed across any note-taking system. Supporting that type of integration would require a greater degree / different type of standardization.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;Consider someone wanting to implement a summarization feature for note-taking systems, agnostic to the specific note-taking system being used. They train a machine learning model that can take a bunch of text notes and produce a quality summary. They implement a way for a user to efficiently select a collection of notes. The UI they choose allows searching by tags and keywords, navigating through the search results with the arrow keys and marking notes and their children for inclusion by pressing enter.&lt;/p&gt;
&lt;p&gt;When the user indicates they&amp;rsquo;ve selected the notes for summarization, they submit them to the feature&amp;rsquo;s ML system, which produces a summary.
if the user likes the summary, they accept it. When accepted, the feature inserts the summary into a dedicated Summarization specific section of the notes, complete with references to each of those notes used to produce the summary.&lt;/p&gt;
&lt;p&gt;This toy feature relies on having batch read access to the notes on the basis of a query, as well as restricted note entry permissions for writing notes back to the system. Using the hypothetical standard we are brainstorming toward in this snippet, such a system could be implemented once, but used by anyone with their notes in any of the note-taking systems that conform to these parts of the standard.&lt;/p&gt;
&lt;p&gt;An even better summarization feature would be one that doesn&amp;rsquo;t require the user to select the notes to summarize. It would automatically identify chunks of notes on a related topic, and summarize those. When it generates a summary, it would offer it to the user, along with mentioning which notes were used in the generation of the summary. The user could choose to accept the summary (in which case it would be saved as explained above), or not to. This version of the features requires whole-notebase access to implement, a slightly more permissive requirement than query-based access.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;What does such a &lt;em&gt;standard&lt;/em&gt; look like in practice? Maybe a useful analogy is thinking of it as an &amp;ldquo;LLVM&amp;rdquo; for notebases &amp;ndash; an &amp;ldquo;LLNB&amp;rdquo; if you will (unofficially standing for low level notebase, but not officially standing for anything&amp;hellip;)&lt;/p&gt;
&lt;p&gt;For each note-taking system we could implement a lossless bidirectional transform to a standard &amp;ldquo;intermediate representation&amp;rdquo;. Tools and plugins could be written to operate on this shared representation, and they could then be deployed against any note-taking system with supported transformations to and from the shared representation.&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;intermediate representation&amp;rdquo; compiler analogy isn&amp;rsquo;t perfect though, since I don&amp;rsquo;t think it captures the desired incremental export, view, and subscription features we&amp;rsquo;d like in the LLNB system. We don&amp;rsquo;t want to have to process an entire notebase to get it&amp;rsquo;s LLNB form, and we don&amp;rsquo;t want to have to overwrite an entire notebase to update it from a modified LLNB. Critical to this working is having the LLNB track its own updates and be able to export just what has changed, and similarly having the note-taking systems able to report either a full update (if no state about the notebase is known), or just an incremental update (if the notebase state was already exported recently). One way to achieve this would be to have an API that gives a diff between an earlier state of a notebase (say, indicated by a commit hash or timestamp) and the current state.&lt;/p&gt;
&lt;p&gt;How about system-specific features? When features of a specific note-taking system X are used, they can appear in the intermediate representation as metadata. This metadata can be constituted appropriately when transferred back to X, or can be included as text if instead transferred to system Y. To make this concrete, support Notion has a geographic map feature that someone has used in their notes, but that is not supported by Roam. If the export their notes to LLNB, the map state is saved as e.g. {location: new jersey, zoom: 5}. If the notes are then imported back into Notion, the map will be restored. If instead the notes are imported into Roam, which lacks the map feature, the data about how the map feature will be included instead. So, if the notes are later exported from Roam and imported back into Notion, the map will be restored.&lt;/p&gt;
&lt;p&gt;If the state of some feature is complicated and not practically serializable as a note, it can be stored outside the notebase, e.g. in Dropbox or Google Drive or whatever is appropriate, with a reference to that external storage medium used as the state.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Note-taking System Interoperability</title>
      <link>https://davidbieber.com/snippets/2021-10-09-note-taking-system-interop/</link>
      <pubDate>Sat, 09 Oct 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-10-09-note-taking-system-interop/</guid>
      
      <description>&lt;p&gt;What would be a good &lt;em&gt;standard&lt;/em&gt; for note-taking software to use to support development of system-agnostic tools like Go Note Go? In this snippet I discuss the value such a standard could provide; I expect it will be useful in future brainstorming for what exactly would go into such a standard.&lt;/p&gt;
&lt;p&gt;I am building Go Note Go as a note-taking entry point, possibly with some basic retrieval features (e.g. &amp;ldquo;read back the last two notes I took&amp;rdquo;). I currently use Roam Research as my main note-taking system, but I&amp;rsquo;m not wedded to it forever.&lt;/p&gt;
&lt;p&gt;So, I&amp;rsquo;m building Go Note Go to work with any note-taking system. To do so, I need a distinct uploader implementation for every note-taking system that I support. I&amp;rsquo;m reaching out to the developers at the note-taking systems to assist with this effort. It would be lovely if there was a standard, to reduce the amount of work required here.&lt;/p&gt;
&lt;p&gt;For Go Note Go, only note &lt;em&gt;entry&lt;/em&gt; is required. If Go Note Go wanted to interact with the notes in a deeper way while continuing to support multiple note-taking systems (e.g. to support spaced repetition, or grocery lists, or reviewing a topic), then a standard would be even more important. Specialized implementations for each note-taking system would become largely untenable.&lt;/p&gt;
&lt;p&gt;It is both common and important that hobbyists develop tools for interacting with their notes. Roam Research has 
&lt;a href=&#34;https://roamjs.com/extensions&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;hundreds&lt;/a&gt; 
&lt;a href=&#34;https://roamresearch.com/#/app/roam-depot-developers/page/8yTj7WxQi&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;of&lt;/a&gt; 
&lt;a href=&#34;https://bjosephburch.com/ultimate-roam-tool-kit/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;extensions&lt;/a&gt; developed by the Roam community. Obsidian has hundreds of 
&lt;a href=&#34;https://obsidian.md/plugins&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;plugins&lt;/a&gt;. This is part of what makes these tools so powerful.&lt;/p&gt;
&lt;p&gt;To my knowledge, no one has written a tool for both Roam and Obsidian simultaneously. I want people to be able to make tools for all of Roam, Obsidian, IdeaFlow, Mem, RemNote, Notion, Logseq, Athens, Dendron, all the ones I don&amp;rsquo;t know about, and whatever comes next.&lt;/p&gt;
&lt;p&gt;Some of these tools will live inside the note-taking editor. Others, like Go Note Go, merely have to interact with the note-taking system, but do not need to become &lt;em&gt;part&lt;/em&gt; of the note-taking system.&lt;/p&gt;
&lt;p&gt;Some key areas where standards could provide value are: note representation, entry, navigation, editing, and search. Also valuable, but conceptually separate, would be a standard for UI extension.&lt;/p&gt;
&lt;p&gt;Standards would make the development of system-agnostic tools easier. This includes novel note entry systems (e.g. 
&lt;a href=&#34;https://davidbieber.com/projects/shh-shell&#34;&gt;shh-shell&lt;/a&gt; and 
&lt;a href=&#34;https://davidbieber.com/projects/go-note-go&#34;&gt;Go Note Go&lt;/a&gt;, but also note entry systems for new domains, such as for doctor&amp;rsquo;s offices or for while you&amp;rsquo;re cooking, or for use in virtual reality). It also would support advancements in spaced repetition, multiplayer note-taking, and would enable new features like note summarization and highlight extraction to become available in all the different note-taking systems at once.&lt;/p&gt;
&lt;p&gt;In addition to all these applications, standards will make import/export/backup tools easier to build. This can reduce vendor lock in, and more importantly can reduce data loss by enabling robust backups. Today, switching my notes to another system would be a small hassle (e.g. Handling block references in the transfer might require some specialized treatment. And I&amp;rsquo;d need to do some work to set up a spaced repetition system like the one I&amp;rsquo;m currently using in Roam.)&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll say a few words about some of these ideas that would benefit from standards.&lt;/p&gt;
&lt;p&gt;(1) &lt;strong&gt;Advancements in spaced repetition.&lt;/strong&gt; Having a spaced repetition system inside of a note-taking system is far lower friction than a separate app. Improvements to SRS that work across all note-taking systems would be warmly welcomed. I believe there are also significant advances to be made in community-scale spaced repetition, where cards and knowledge are drawn from not just your own notes, but from your community&amp;rsquo;s notes (including peers and teachers), and where your review schedule is similarly influenced not only by your own learning progress, but also by the progress of your community. This deserves a separate snippet, but I&amp;rsquo;ll note here a possibility that community-scale spaced repetition enables: it allows for community-level learning priorities, which may include diversity of topic. For example the members of a community might decide they want to ensure that all of its history is adequately studied (or any other collection of topics), not just the most interesting parts. Deciding individually, the members of the community might choose to study overly overlapping parts of its history. Using a community-scale spaced repetition algorithm, the choice of what to study can still predominantly be left up to individuals, but with small guidance from the centralized algorithm the community can ensure complete coverage of all the desired topics.&lt;/p&gt;
&lt;p&gt;(2) &lt;strong&gt;Multiplayer Note-taking&lt;/strong&gt; Let&amp;rsquo;s say I&amp;rsquo;m doing research on a topic, and a colleague is doing research on a related topic. I might want to search through my colleague&amp;rsquo;s notes, and reference some of them from my own notes. This isn&amp;rsquo;t even possible in most note-taking systems today, but I think is either a future or work-in-progress feature of Roam, Athens, and Obsidian. Being able to do this cross-system would be so much better than only being able to do it within a system. A standard agreed upon by the different note-taking system developers would be necessary to support this.&lt;/p&gt;
&lt;p&gt;(3) &lt;strong&gt;Summarization and highlight extraction&lt;/strong&gt; Summarization is a feature not yet present in any note-taking system, but surely one that will be added to many systems in the future. It is the ability to get a (machine generated) summary of a large chunk of notes automatically. This is marginally useful when reviewing your own notes, but is even more useful in conjunction with multiplayer features. Being able to view a summary of other people&amp;rsquo;s notes or an entire community&amp;rsquo;s notes will allow multiplayer systems to scale to larger groups of people while remaining useful. Highlight extraction is a related future feature, enabling users to quickly find the most important parts of a notebase. As with summarization, this is useful for an individuals notes, and doubly useful for a multiplayer notebase.&lt;/p&gt;
&lt;p&gt;For each of these ideas, standards would be useful for allowing feature development to benefit users of all systems simultaneously, and for allowing users of one note-taking system to benefit from notes taken in another system. The space of possible applications is also much larger than my brainstorming above indicates. Specifically, the set of domain-specific activities one might want to perform with their notes is quite large (planning a family gathering, studying for a med school exam, writing a novel, etc.) Specialized applications could be built for each of these, and it should not matter where the relevant notes were taken. Different systems will always have their pros and cons for different types of content, but we don&amp;rsquo;t need to reinvent the wheel so frequently for use-cases that make sense in the context of all these different systems.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Spaced Repetition Update</title>
      <link>https://davidbieber.com/snippets/2021-10-05-spaced-repetition-update/</link>
      <pubDate>Tue, 05 Oct 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-10-05-spaced-repetition-update/</guid>
      
      <description>&lt;p&gt;Previously I&amp;rsquo;ve written about 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-01-02-spaced-repetition-in-roam-research/&#34;&gt;how I do spaced repetition in Roam Research&lt;/a&gt; using Leitner Boxes. I&amp;rsquo;m still doing spaced repetition daily, but my methods have changed a bit. So, let me give you the update.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m still doing spaced repetition in Roam, but I&amp;rsquo;ve moved away from the Leitner Box approach. Now instead I use 
&lt;a href=&#34;https://github.com/aidam38/roamsr&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Adam Krivka&amp;rsquo;s roam/sr&lt;/a&gt;. With this approach, each card has it&amp;rsquo;s own review schedule instead of being lumped together into a small total number of review buckets. Also, the review process is nicer looking and lower friction (especially on mobile) compared to my original Leitner Box approach.&lt;/p&gt;
&lt;p&gt;I made the switch to roam/sr on July 5, and haven&amp;rsquo;t missed a day since. It&amp;rsquo;s been three months so far. Let&amp;rsquo;s keep it up! In that time, I&amp;rsquo;ve created 1383 cards. That&amp;rsquo;s 15 new cards a day.&lt;/p&gt;
&lt;p&gt;The main way in which I make cards these days is with my 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-07-29-note-taking-flow/&#34;&gt;Browserflow Note-taking Flow&lt;/a&gt;. With this flow, I highlight &lt;em&gt;part&lt;/em&gt; of a sentence or paragraph and press c (for a sentence) or b (for a paragraph) to turn that sentence or paragraph  into a &amp;ldquo;cloze&amp;rdquo; task. The highlighted part becomes a fill-in-the-blank and the whole sentence/paragraph becomes a card in my spaced repetition system.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m also using Adam Krivka&amp;rsquo;s 
&lt;a href=&#34;https://roamresearch.com/#/app/roam-depot-developers/page/fIR-UkBAL&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;image occlusion plugin&lt;/a&gt; for Roam to create visual cloze tasks. With it, I&amp;rsquo;ll mask out part of an image to create a spaced repetition card asking me to predict what&amp;rsquo;s missing in the image.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m mainly using spaced repetition to study Croatian. I also have plenty of cards relating to medicine, astrophysics, economics, science in the news, computer science and machine learning, math, and more. There&amp;rsquo;s a long tail of topics I dove into, taking notes with Browserflow, that now populate my cards.&lt;/p&gt;
&lt;p&gt;A typical review session is about 50-80 cards, with a couple of days peaking over 100 cards. I add cards in clusters, so my &amp;ldquo;new cards&amp;rdquo; pile varies from having 0 cards to having about 100 cards. I limit myself to studying 25 new cards per day, occasionally allowing this to reach up to 50 or 75.&lt;/p&gt;
&lt;p&gt;Spaced repetition has become a morning habit for me. Usually the first thing I do each morning is a review session, whereas I more often make new cards at night. Though I&amp;rsquo;ve kept the habit up for over 90 days consecutively (and have been doing SRS for over a year now off-and-on), I expect the real challenge to my habit will come the next time I travel extensively. Hopefully by being aware of this challenge now, I&amp;rsquo;ll be able to keep the habit through it in the future.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Writing a Snippet with Go Note Go</title>
      <link>https://davidbieber.com/snippets/2021-09-27-snippet-on-go-note-go/</link>
      <pubDate>Mon, 27 Sep 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-09-27-snippet-on-go-note-go/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;ve been developing and concurrently using Go Note Go for two weeks now, and in that time I have come to love the frictionless way it allows me to dump thoughts into the machine. I don&amp;rsquo;t have a chance to reread what I&amp;rsquo;ve written. There&amp;rsquo;s no going back and rewording something. And more than that, there&amp;rsquo;s no waiting for the characters to show up, or switching tabs, or spell checking or anything like that.&lt;/p&gt;
&lt;p&gt;This is the first time I&amp;rsquo;m writing a snippet using Go Note Go.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve thought about writing a snippet about Go Note Go over the last two weeks, but I decided not to until yesterday when I finally stopped keeping Go Note Go to myself.
I thought maybe there would be value in getting Go Note Go polished, e.g. writing a getting started guide or even a sales page, and &lt;em&gt;then&lt;/em&gt; publishing it once people can actually use it themselves.
But I decided against that.&lt;/p&gt;
&lt;p&gt;Done is better than perfect.&lt;/p&gt;
&lt;p&gt;I might not find a good way to package Go Note Go so that people can start using it with relative ease.
Certainly I can do better than I have so far − there&amp;rsquo;s little help at all for someone to put together their own system.
That said, a motivated individual could in principle piece together their own Go Note Go from what I&amp;rsquo;ve published now.
And I&amp;rsquo;d be happy to help them do it.&lt;/p&gt;
&lt;p&gt;And even if someone had to ask too many questions or can&amp;rsquo;t reproduce the full setup, maybe they&amp;rsquo;ll take the concept in a new direction.
&amp;ldquo;Headless note−taking&amp;rdquo; is a broad idea and I&amp;rsquo;ve just scratched the surface.
We can see from shh shell and Go Note Go alone that there are diverse approaches one can take to this broad concept.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like to take it further myself, but more than that I think it&amp;rsquo;s important to start the conversation about headless note−taking since it might be able to help a much broader set of people than it&amp;rsquo;s helping right now.&lt;/p&gt;
&lt;p&gt;Maybe it would be great in classrooms to avoid distractions.
Maybe there are headless audio−only applications for writers, for programmers, for producers, for lawyers and doctors and publicists and influencers and so forth that are just waiting to be developed.
Different keyboard shortcuts could be specialized for different domains. The addition of foot peddles might help some users. Whatever is needed to make this maximally useful for different applications and different people&amp;hellip;&lt;/p&gt;
&lt;p&gt;Maybe it&amp;rsquo;s already super useful for people, but there&amp;rsquo;s just no way for those people to know right now because they can&amp;rsquo;t easily try it, or haven&amp;rsquo;t heard of it and thought about it. This is wishful thinking of course; it might be an esoteric toy that is only useful or fun for a small group, but I&amp;rsquo;m confident that group is larger than just myself.&lt;/p&gt;
&lt;p&gt;So I want to put this out there a little bit. I&amp;rsquo;d like to share it with Conor of Roam, and with Andy Matuschak, and with folks at IdeaFlow and with Notion users, and with Obsidian folks, etc.&lt;/p&gt;
&lt;p&gt;One thing I&amp;rsquo;d like to get out of sharing with these groups is contributors to the extensible uploader side of Go Note Go.
I think it would be so cool if each supported note−taking system had an uploader contributed by someone working at that note−taking system&amp;rsquo;s company. Conor or Bardia could make a contribution to the Roam uploader. Jacob or Linus could write the IdeaFlow uploader. Someone from Obsidian and Notion could provide uploaders for each of those. Now that the GitHub for the project is public, this is easier to start working toward.&lt;/p&gt;
&lt;p&gt;Also, the more I think about the getting started guide, the easier it seems to write. There are only a few steps you really need to follow to get set up. Roughly, it looks like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Acquire the parts (Raspberry Pi, MicroSD card, optional battery pack, USB cords, a speaker and microphone compatible with the Pi (a Voice Bonnet is one option, but any will do.))&lt;/li&gt;
&lt;li&gt;Clone Go Note Go&lt;/li&gt;
&lt;li&gt;Edit config&lt;/li&gt;
&lt;li&gt;Install dependencies&lt;/li&gt;
&lt;li&gt;Put start script in rc.local file to start on startup&lt;/li&gt;
&lt;li&gt;Be sure to configure your wifi wpa config file&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Wishful thinking again: I could probably write a decent guide in under an hour.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Go Note Go is public</title>
      <link>https://davidbieber.com/snippets/2021-09-26-go-note-go/</link>
      <pubDate>Sun, 26 Sep 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-09-26-go-note-go/</guid>
      
      <description>&lt;p&gt;Go Note Go is public! I&amp;rsquo;ve been working on this for two weeks now, and today I made it public!&lt;/p&gt;
&lt;p&gt;
&lt;a href=&#34;https://davidbieber.com/projects/go-note-go&#34;&gt;Read all about it here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;What is it? Go Note Go is a note-taking system for when you’re on the go, with a focus on driving and camping.&lt;/p&gt;
&lt;p&gt;In short, it&amp;rsquo;s a portable keyboard with a microphone and speakers and a beautiful handheld button that you can use to take notes anywhere at all. Driving? Push the button and speak your notes. Camping? Type on the keyboard, powered by a battery pack. The battery lasts all day, and the notes will be uploaded to your central note-taking system as soon as internet becomes available.&lt;/p&gt;
&lt;p&gt;Have a look. Let me know what you think! I&amp;rsquo;ve been using it as I develop it over the last two weeks and I &lt;em&gt;really love&lt;/em&gt; it. I keep it by my computer during the work day. I took it with me to my table tennis tournament yesterday. I&amp;rsquo;ve brought it to the beach. There&amp;rsquo;s no cognitive overhead. There&amp;rsquo;s no latency to slow down your thinking. Just speak, or type, and it works.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Embedded Roam Research</title>
      <link>https://davidbieber.com/snippets/2021-09-12-embedded-roam-research/</link>
      <pubDate>Sun, 12 Sep 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-09-12-embedded-roam-research/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;d like to be able to embed a Roam Research page on my website so that other people can make spaced repetition cards for me.&lt;/p&gt;
&lt;iframe src=&#34;https://roamresearch.com/#/app/commons-db/page/xftkxraPw&#34; width=&#34;100%&#34; height=&#34;400&#34; frameborder=&#34;0&#34; style=&#34;border:0&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;No luck, though.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>GPT-3 for Spaced Repetition</title>
      <link>https://davidbieber.com/snippets/2021-09-08-gpt-3-for-spaced-repetition/</link>
      <pubDate>Wed, 08 Sep 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-09-08-gpt-3-for-spaced-repetition/</guid>
      
      <description>&lt;p&gt;Lately I&amp;rsquo;ve been using Browserflow to create spaced repetition flashcards quickly while browsing the internet.&lt;/p&gt;
&lt;p&gt;To create a card, I highlight a bit of text and press &amp;ldquo;c&amp;rdquo;. This copies the sentence containing the highlight into the card, with the part I highlighted masked out.
It&amp;rsquo;s a cloze task, as in a masked language model.
If instead I push &amp;ldquo;b&amp;rdquo;, it copies the full paragraph containing the highlight, again with the highlight masked out.&lt;/p&gt;
&lt;p&gt;Usually this is a great way to quickly create my flashcards. However, sometimes I get sentences where the subject is unclear without context, e.g. &amp;ldquo;this&amp;rdquo; in &amp;ldquo;Usually this is a great way to quickly create the flashcards.&amp;rdquo; For these, it would be great to automatically rewrite the sentence with the subject pulled in from the surrounding context.&lt;/p&gt;
&lt;p&gt;For example, &amp;ldquo;Usually this is a great way to quickly create the flashcards&amp;rdquo; could be rewritten as &amp;ldquo;Usually &lt;mark&gt;using &amp;ldquo;b&amp;rdquo; and &amp;ldquo;c&amp;rdquo; with Browserflow&lt;/mark&gt; is a great way to quickly create the flashcards.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;As a second example, consider this 
&lt;a href=&#34;http://hyperphysics.phy-astr.gsu.edu/hbase/Solar/meteor.html#c3&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;HyperPhysics page on the Murchison Meteorite&lt;/a&gt;. Speaking about the Murchison Meteorite, the page says &amp;ldquo;Seventy four amino acids were found in it, compared to the 20 which are characteristic of life.&amp;rdquo; I&amp;rsquo;d love to make a card saying &amp;ldquo;Seventy four &lt;mark&gt;amino acids&lt;/mark&gt; were found in the Murchison Meteorite, compared to the 20 which are characteristic of life.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;However, if I highlight &lt;mark&gt;amino acids&lt;/mark&gt; and press &amp;ldquo;c&amp;rdquo;, the generated card instead reads: &amp;ldquo;Seventy four &lt;mark&gt;amino acids&lt;/mark&gt; were found in &lt;em&gt;it&lt;/em&gt;, compared to the 20 which are characteristic of life.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;So, the challenge I present you with is: write a program that takes a sentence, and it&amp;rsquo;s surrounding context, and rewrites the sentence so that it is clear even out of context.&lt;/p&gt;
&lt;p&gt;Having played with GPT-3 and Codex recently, this seems well within the scope of large pretrained language models. I expect that with some careful prompting, a large language model could excel at this task without even any fine-tuning, just taking advantage of few shot learning. Is this the best or simplest approach? Likely it isn&amp;rsquo;t, but it may be the approach that minimizes development time and is easiest to repurpose for other similar (or dissimilar) projects in the future.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Phone in the kitchen evaluation</title>
      <link>https://davidbieber.com/snippets/2021-08-22-phone-in-kitchen-eval/</link>
      <pubDate>Sun, 22 Aug 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-08-22-phone-in-kitchen-eval/</guid>
      
      <description>&lt;p&gt;Last month I decided to start keeping my phone in the kitchen while I&amp;rsquo;m in the house. I said I&amp;rsquo;d evaluate the decision after 6 weeks and decide whether to recommit. It&amp;rsquo;s been six weeks, and I think it was an excellent decision. I will absolutely continue doing this going forward.&lt;/p&gt;
&lt;p&gt;I find I get more time in the mornings, because scrolling in bed or on the toilet isn&amp;rsquo;t really an option. Similarly in the evenings, scrolling in bed before going to sleep isn&amp;rsquo;t something I can do by accident. I do find I spend more time in the kitchen, in order to use my phone. So, I haven&amp;rsquo;t eliminated mindless scrolling altogether. My phone usage has decreased considerably overall though.&lt;/p&gt;
&lt;p&gt;The oddest thing about it is that I don&amp;rsquo;t always have a way of knowing the itme when I wake up. I may want to put a non-phone clock in the bedroom to compensate for this.&lt;/p&gt;
&lt;p&gt;Sometimes over the last six months I would find I accidentally would bring my phone with me to my desk. Usually this would happen after going out of the house for lunch (taking my phone with me). When I would return to the house, I would have my phone in my pocket, and I wouldn&amp;rsquo;t always remember to put it in the kitchen. Once the phone reached my desk, sometimes I would then inadvertently scroll! Whenever I notice that I&amp;rsquo;ve brought my phone somewhere in the house outside the kitchen, it&amp;rsquo;s clear the right thing for me to do under this silly system I&amp;rsquo;ve chosen for myself, is to bring it back to the kitchen.&lt;/p&gt;
&lt;p&gt;It can be tempting to make only small violations to the rule, but I&amp;rsquo;ve realized it&amp;rsquo;s best not to fall for such temptations. There&amp;rsquo;s a bathroom just outside the kitchen, and I am tempted often to take the phone with me from the kitchen to the bathroom. I stop at the threshold to the kitchen, and do not cross if I&amp;rsquo;m holding my phone. Perhaps I stand in the threshold for a few minutes, finishing my phone usage before leaving. I put the phone down before exiting.&lt;/p&gt;
&lt;p&gt;If I were to take the phone to the bathroom, I know what would happen. I would think, going in, that I will just use the phone for one particular purpose. However, as soon as I turn the screen on I would notice something that would put a different purpose into my mind. Maybe it&amp;rsquo;s a text message, or an app icon, or a notification. I think, switching tasks, that it&amp;rsquo;s a small diversion and I will momentarily return to the original purpose. However, moments later while completing the secondary task, my mental stack will erode, and the primary task will no longer be at the forefront of my brain. I&amp;rsquo;ll no longer be thinking about the one-and-done approach to phone usage, and now the potential for mindless scrolling has emerged.&lt;/p&gt;
&lt;p&gt;So, the phone stays in the kitchen. I will keep this rule for myself, at least as long as I live here in this house.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Codex as a Programming Language</title>
      <link>https://davidbieber.com/snippets/2021-08-16-codex-pl/</link>
      <pubDate>Mon, 16 Aug 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-08-16-codex-pl/</guid>
      
      <description>&lt;p&gt;In the 
&lt;a href=&#34;https://www.youtube.com/watch?v=SGUCcjHTmGY&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;impressive demo of OpenAI&amp;rsquo;s &lt;em&gt;Codex&lt;/em&gt; programming system&lt;/a&gt;,
the presenters suggest that Codex enables natural language to be used as a new kind of programming language.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how that might look, followed by one problem with the suggestion.&lt;/p&gt;
&lt;p&gt;A natural-language programmer writes natural language prompts, and Codex transforms them into source code.
The Codex model is made deterministic, such that rerunning the model on the prompts always produces the same source code.
The user can make further modifications to the source code that the model produces.
The result is two parallel streams of text: (1) the natural language, and (2) the final source code.
These parallel streams can be saved in version control, shared, modified, remixed, and run.&lt;/p&gt;
&lt;p&gt;A non-programmer might still be able to make modifications, simply by modifying the natural language text, without making modifications to the source code at all.
This could be a way to learn a bit about programming for the curious non-programmer too, as they can observe the changes to the source code
that result from changing the natural language text.&lt;/p&gt;
&lt;p&gt;It is tempting to think that only the diff between the source code produced by the model and the final source code need be stored.
However, this doesn&amp;rsquo;t hold up. The prompt when generating source code includes all earlier source code in the file. So if a programmer wants to modify
a natural language prompt or piece of code earlier in a file, it could invalidate all the generated code later in the file. Rerunning the model on the new state of the program wouldn&amp;rsquo;t reproduce the source code verbatim, even with the model made deterministic.&lt;/p&gt;
&lt;p&gt;The editor showing the program might be modified to reflect this. I envision it showing two columns, the left column with natural language text and the right column, aligned with the left, showing the source code. A block of text and code shows with a green background if the model, when run on the text, produces exactly the source code on the right. It shows with yellow if the source code produced by the model differs slightly from the actual code in the block (and the diff is highlighted). And it shows in red if no simple diff distinguishes the model&amp;rsquo;s output from the actual code in the block.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Decentralized Global Spaced Repetition (incomplete)</title>
      <link>https://davidbieber.com/snippets/2021-08-16-dgsrs/</link>
      <pubDate>Mon, 16 Aug 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-08-16-dgsrs/</guid>
      
      <description>&lt;p&gt;I envision a decentralized global spaced repetition system (DGSRS).
Anyone in the world can participate, submitting entries that they&amp;rsquo;d like the world to remember.
To participate, you both need to review entries that others want reviewed, and submit an occasional entry yourself.&lt;/p&gt;
&lt;p&gt;There are two main benefits to the individual participating in the DGSRS:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;You can ensure that the idea you care about is never forgotten.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can be exposed to interesting new ideas&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Roughly, the system acts like this:&lt;/p&gt;
&lt;p&gt;Each participant can submit entries. When an entry is submitted, provided the submitter is in good standing and the entry doesn&amp;rsquo;t get flagged as being inappropriate or out of scope (too hard for a single entry, nonsense, etc), the system guarantees the entry will be remembered forever.&lt;/p&gt;
&lt;p&gt;This is appealing to countries trying to preserve a language, to researchers who think they have a good idea that the world isn&amp;rsquo;t latching on to,
to conlang enthusiasts trying to bring a new language into existance, to first-time authors, and to creatives.&lt;/p&gt;
&lt;p&gt;&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Spaced Repetition at a Community Scale</title>
      <link>https://davidbieber.com/snippets/2021-08-15-community-spaced-repetition/</link>
      <pubDate>Sun, 15 Aug 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-08-15-community-spaced-repetition/</guid>
      
      <description>&lt;p&gt;Spaced repetition is great for individual learners, but can we apply it to the preservation of institutional knowledge?&lt;/p&gt;
&lt;p&gt;What would that look like? Maybe it means dedicating some fraction of some employee time to revisiting old documentation and bringing it up to date.
Maybe it involves periodic runthroughs of playbooks to ensure they&amp;rsquo;re still working.&lt;/p&gt;
&lt;p&gt;Is there a reason to want the exponential backoff property of individual spaced repetition when applying it to institutions?&lt;/p&gt;
&lt;p&gt;How many people need to be familiar with an idea to adequately ensure that idea will be &amp;ldquo;cross-pollinated&amp;rdquo; with other ideas it pairs well with?
Are there old but important ideas that have fallen out of favor, that a global &amp;ldquo;spaced repetition&amp;rdquo; employed by the whole scientific community would have pointed us to, leading to useful connections otherwise unseen?&lt;/p&gt;
&lt;p&gt;In such a multiplayer system, how is it decided what ideas are worth revisiting, and how often? Is it an automated system based on citations, or based on committees? Is it decentralized, with each participant in control of their own SRS and its algorithm, or is a central governing body required. I expect a decentralized system requiring little to no trust could be devised.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like to revisit this idea and consider it a little more deeply &amp;ndash; after some delay, of course &amp;ndash; in the future.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>CRISPR Gardening</title>
      <link>https://davidbieber.com/snippets/2021-08-09-crispr-gardening/</link>
      <pubDate>Mon, 09 Aug 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-08-09-crispr-gardening/</guid>
      
      <description>&lt;p&gt;Everyone likes their veggies crisp, so who wouldn&amp;rsquo;t want CRISPR veggies?
After reading The Code Breaker, I&amp;rsquo;ve become progressively more excited about the possibilities that gene editing will bring in the coming decades.&lt;/p&gt;
&lt;p&gt;Or sooner? The technology has matured remarkably quickly and is developing incredibly fast.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t have a full grasp of where things stand today, but this is just a snippet, so I won&amp;rsquo;t let that stop me from speculating about where we&amp;rsquo;re heading. Take everything here with a grain of salt.&lt;/p&gt;
&lt;p&gt;Today, we can perform germline gene editing somewhat reliably. It&amp;rsquo;s been done on human beings; the scientist who performed this first, I believe has gone to jail for the ethics violations involved in doing so. Our interest in this snippet, however, doesn&amp;rsquo;t have the full set of ethical qualms that applying gene editing to humans has. We&amp;rsquo;re interested in applying gene editing to plants.&lt;/p&gt;
&lt;p&gt;GMOs aren&amp;rsquo;t knew, but they&amp;rsquo;re (at least in the big picture) in their infancy. Today, particular seeds have been patented, leading to monopolistic anti-competitive practices by, for example, Monsanto. This doesn&amp;rsquo;t have to be the way gene-editing looks in the future. There&amp;rsquo;s a chance it&amp;rsquo;s more widely accessible and commonly used in ordinary people&amp;rsquo;s homes in the future. Not just through people purchasing GMO seeds (already modified) from a store and planting them, but rather by modifying the genome of a seed in their own home and then planting it in their own garden.&lt;/p&gt;
&lt;p&gt;In a very hand-wavy sort of way, here&amp;rsquo;s a bit of what this future history looks like.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;COVID makes in-home PCR more affordable more common. Since there&amp;rsquo;s demand for in-home viral testing, the components and skills involved in bioengineering start becoming more commonplace. This is already happening.&lt;/li&gt;
&lt;li&gt;Our understanding of the genome is increasing every week. This is already happening.&lt;/li&gt;
&lt;li&gt;People will be able to modify the genome of plants using a library of known edits. E.g. take the basil genome, replace GAAT at position 1004 with TAAG, and you&amp;rsquo;ll get freeze-resistant basil.&lt;/li&gt;
&lt;li&gt;Eventually people will be able to use software to create genomes using higher-level constructs than directly writing the base-pairs in the desired DNS.&lt;/li&gt;
&lt;li&gt;First this will mean listing out proteins instead of individual base-pairs.&lt;/li&gt;
&lt;li&gt;Later it will involve listing out multi-protein mechanisms, or higher level traits.&lt;/li&gt;
&lt;li&gt;Eventually it will shift from being &amp;ldquo;like programming&amp;rdquo; to a no-code process, where even children will be able to design plants. They&amp;rsquo;ll sketch the desired leaf shapes, choose the yummiest flavor profiles, select the environment in which the plant should thrive, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The advantages of CRISPR gardening over traditional gardening include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You can customize plants that are tailor made for your diet&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;hellip; for your climate&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;hellip; for your aesthetic&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;hellip; to express your creativity&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can easily share a custom genome on the internet. Sharing the diff from a known genome takes less bandwidth, but even sharing a full genome is easy. This is far easier and more scalable than sharing physical seeds.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In order to get to this point, it would be useful to have &amp;ldquo;factories&amp;rdquo; / robot-biotech-gardens systematically mutating plant genomes, growing the resultant plants in various ways, and recording the effects. The individual components of this vision are already underway. Companies like IronOx use robots to grow vegetables in warehouses without human intervention. Other companies provide robot-performanced wetlab experiments. Now what we need is to bring these players together, so that we can most efficiently more toward fully understanding plant genomes and the CRISPR gardening era that awaits.&lt;/p&gt;
&lt;p&gt;One day, when I have my own house and CRISPR garden, I&amp;rsquo;m going to have garden gnomes &amp;ndash; or g-gnomes for short.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Browserflow Note-taking Flow</title>
      <link>https://davidbieber.com/snippets/2021-07-29-note-taking-flow/</link>
      <pubDate>Thu, 29 Jul 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-07-29-note-taking-flow/</guid>
      
      <description>&lt;p&gt;Quick update on the note-taking Browserflow flow I&amp;rsquo;ve been building: 
&lt;a href=&#34;https://browserflow.app/shared/51b5b7af-3124-4989-9771-36e9f236e1e7&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://browserflow.app/shared/51b5b7af-3124-4989-9771-36e9f236e1e7&lt;/a&gt;:&lt;/p&gt;
&lt;h2 id=&#34;how-it-works&#34;&gt;How it works&lt;/h2&gt;
&lt;p&gt;When you run it, it injects some js into the page you&amp;rsquo;re viewing enabling a handful of keyboard shortcuts to enable clipping text into Roam from anywhere on the web.&lt;/p&gt;
&lt;p&gt;If you navigate to a new page, it will run that js on the new page. So it keeps the keyboard shortcuts active even if you follow links.&lt;/p&gt;
&lt;p&gt;It also removes the status overlay, so you can interact with the page more easily.&lt;/p&gt;
&lt;h2 id=&#34;the-keyboard-shortcuts-currently-are&#34;&gt;The keyboard shortcuts currently are:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;enter&lt;/code&gt;: saves the current selection as a note to Roam&lt;/li&gt;
&lt;li&gt;&lt;code&gt;q, !, @, *, &amp;gt;&lt;/code&gt;: saves the current selection as a note to Roam tagged as a {question, &amp;ldquo;Wow&amp;rdquo;, Share, key idea, or block quote} (I don&amp;rsquo;t really use these)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;p&lt;/code&gt;: saves the paragraph containing the selection to Roam, with the selection highlighted&lt;/li&gt;
&lt;li&gt;&lt;code&gt;s&lt;/code&gt;: Asks for an element in browserflow. Saves a screenshot of the element to Roam. Doesn&amp;rsquo;t work. (hmm&amp;hellip; why not?)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;h&lt;/code&gt;: saves the sentence containing the selection to Roam, with the selection highlighted&lt;/li&gt;
&lt;li&gt;&lt;code&gt;c&lt;/code&gt;: saves the sentence containing the selection to Roam as a &amp;ldquo;cloze&amp;rdquo; (fill-in-the-blank) task for spaced repetition, with the selection as the fill-in-the-blank&lt;/li&gt;
&lt;li&gt;&lt;code&gt;b&lt;/code&gt;: (big cloze) saves the paragraph containing the selection to Roam as a &amp;ldquo;cloze&amp;rdquo; (fill-in-the-blank) task for spaced repetition, with the selection as the fill-in-the-blank&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.&lt;/code&gt;: quit (I use this to reenable keyboard shortcuts for tab switching)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;some-feature-requests--debug-things&#34;&gt;Some feature requests / debug things&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Would be nice to keep some status indicator, just in the corner or page title instead of blocking the full page.&lt;/li&gt;
&lt;li&gt;It depends on a couple other flows. Would be nice to be able to share just a single link.&lt;/li&gt;
&lt;li&gt;It switches to the roamresearch.com tab and back whenever you save a note. Would be nice if this worked even if roam were in a different window. The user shouldn&amp;rsquo;t have to care about exactly where roam is open.&lt;/li&gt;
&lt;li&gt;Why doesn&amp;rsquo;t the element screenshotting work?&lt;/li&gt;
&lt;li&gt;Would be nice to allow tab switching in a flow without having to quit the flow.&lt;/li&gt;
&lt;li&gt;For a note-taking flow like this, it can easily be running for hours. Doesn&amp;rsquo;t mix super well with the free tier of billing.&lt;/li&gt;
&lt;li&gt;A few of these could be solved with an &amp;ldquo;Enable interaction with page&amp;rdquo; action&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;the-dependency-flows-needed-to-check-it-out-are&#34;&gt;The dependency flows needed to check it out are:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://browserflow.app/shared/ba6eb2f0-a3d1-4bc3-9f21-5ca18af0b247&#34;&gt;https://browserflow.app/shared/ba6eb2f0-a3d1-4bc3-9f21-5ca18af0b247&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://browserflow.app/shared/486ef3eb-8d2b-48bf-8fee-22963dc74b88&#34;&gt;https://browserflow.app/shared/486ef3eb-8d2b-48bf-8fee-22963dc74b88&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://browserflow.app/shared/8e066128-2f87-468f-842f-3f006f0a2e71&#34;&gt;https://browserflow.app/shared/8e066128-2f87-468f-842f-3f006f0a2e71&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To try out the flow, you&amp;rsquo;ll need Browserflow, an open Roam tab, and all four flows linked in this snippet. Run the first flow (&amp;ldquo;Roam: Highlights&amp;rdquo;) on a web page (with Roam open in a different tab in the same window). Highlight some text, (say, the words &amp;ldquo;some text&amp;rdquo; in this sentence), and hit enter. You can try any of the shortcuts listed above. Notice as the flow copies your selection into your daily notes organized by time and website.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Why table tennis strokes end at the forehead</title>
      <link>https://davidbieber.com/snippets/2021-07-22-forehead-is-forward/</link>
      <pubDate>Thu, 22 Jul 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-07-22-forehead-is-forward/</guid>
      
      <description>&lt;p&gt;It makes sense now! It was really a Eureka! moment on Tuesday when I figured it out. The stroke ends at the forehead because the stroke is much more &lt;em&gt;forward&lt;/em&gt; than I was making it.&lt;/p&gt;
&lt;p&gt;Recap: All the much better players&#39; forehands end at their foreheads. Mine ends across my chest on the left side of my body. When I try to end my forehand by my forehead, I mess it up terribly. Until now.&lt;/p&gt;
&lt;p&gt;
&lt;a href=&#34;https://davidbieber.com/snippets/2021-07-10-forehand-to-forehead&#34;&gt;Two weeks ago&lt;/a&gt; I came up with the following reasons / hypotheses for why a good stroke would end at the forehand. They were:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Lower to the table is better&lt;/li&gt;
&lt;li&gt;Each stroke should prepare for the next stroke&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t cut the stroke short&lt;/li&gt;
&lt;li&gt;Balance many concerns (1, 2, 3, hitting up and forward through the path of the ball, hitting toward the target, keeping balance, preparing for next stroke)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These are all valid reasons, but they didn&amp;rsquo;t do it for me. Then, on Tuesday (two days ago), it clicked. If I focus on hitting forward, the stroke comes out much better.&lt;/p&gt;
&lt;p&gt;This is a bit counterintuitive since my forehead is up and right, not forward, relative to where my stroke used to end. Still, by focusing on hitting more forward, it seems I cannot cut the stroke short and I don&amp;rsquo;t move as much to the left. This should reduce side spin, maybe increase top spin, and definitely increase power on my strokes.&lt;/p&gt;
&lt;p&gt;Now, I&amp;rsquo;ve only had the opportunity to play a small amount since making this realization. It&amp;rsquo;s still going to take lots of practice to incorporate this more fully into my game. It feels good though, the strokes are strong and natural. It doesn&amp;rsquo;t feel rote, but it does feel mostly intuitive, which is a good place to start from. Contrast this with when I was trying to land the stroke at my forehead. For those attempts, the stroke felt unnatural and I would usually miss.&lt;/p&gt;
&lt;p&gt;Looking forward to drilling my new stroke extensively tonight.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Weak and Strong Law of Large Numbers</title>
      <link>https://davidbieber.com/snippets/2021-07-18-laws-of-large-numbers/</link>
      <pubDate>Sun, 18 Jul 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-07-18-laws-of-large-numbers/</guid>
      
      <description>&lt;p&gt;$X_i$s are i.i.d random variables with finite expected value.&lt;/p&gt;
&lt;p&gt;$S_n$ is the sum of first $n$ random variables (the sample mean).&lt;br/&gt;
$\mu$ is the true mean (the population mean).&lt;/p&gt;
&lt;p&gt;Both the &lt;em&gt;Weak Law of Large Numbers&lt;/em&gt; and the &lt;em&gt;Strong Law of Large Numbers&lt;/em&gt; say that sample mean likely converges to the population mean as sample size increases.&lt;/p&gt;
&lt;p&gt;The Weak law guarantees &lt;em&gt;convergence in probability&lt;/em&gt;.&lt;br/&gt;
The Strong law guarantees &lt;em&gt;almost sure convergence&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Weak law: $\lim\limits_{n \to \infty} \text{Pr}\left(|S_n - \mu| &amp;lt; \epsilon\right) = 1$&lt;br/&gt;
Strong law: $\text{Pr}\left(\lim\limits_{n \to \infty} S_n = \mu\right) = 1$&lt;/p&gt;
&lt;p&gt;Neither occurence of &amp;ldquo;$=1$&amp;rdquo; means that any event is guaranteed. There&amp;rsquo;s simply infinitesimal probability that an event does not occur.&lt;/p&gt;
&lt;p&gt;The weak law says that for any threshold distance from the true mean $\epsilon$ that you select, as the number of samples increases, the probability that the sample mean is within $\epsilon$ from the true mean approaches one. Even as the number of samples increases there is still the possibility of the sample mean being further than $\epsilon$ from the true mean; that possibility simply approaches being infinitesimal as the number of samples increases.&lt;/p&gt;
&lt;p&gt;The strong law similarly doesn&amp;rsquo;t guarantee that the sample mean must ever equal the true mean. It says that with probability 1 (aka &amp;ldquo;almost surely&amp;rdquo;) the limit of the sample mean equals the true mean.
The reason we call probability 1 &amp;ldquo;almost surely&amp;rdquo; rather than &amp;ldquo;surely&amp;rdquo; is that there are still valid sequences of samples where the sample mean doesn&amp;rsquo;t approach the true mean; these sample outcomes are simply an infinitesimal fraction of the total sample space.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Notes from setting up a new computer</title>
      <link>https://davidbieber.com/snippets/2021-07-11-setting-up-computer/</link>
      <pubDate>Sun, 11 Jul 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-07-11-setting-up-computer/</guid>
      
      <description>&lt;h3 id=&#34;1-configuring-chrome&#34;&gt;1. Configuring Chrome&lt;/h3&gt;
&lt;p&gt;Log into my personal account and my corp account. Chrome extensions sync automatically. A few of them prompt me to log in. No hassle here.&lt;/p&gt;
&lt;h3 id=&#34;2-downloading-staple-software&#34;&gt;2. Downloading Staple Software&lt;/h3&gt;
&lt;p&gt;Download Sublime Text. Download Spectacle. Remap modifier keys. Configure Spectacle.&lt;/p&gt;
&lt;h3 id=&#34;3-set-up-terminal&#34;&gt;3. Set up Terminal&lt;/h3&gt;
&lt;p&gt;Set theme. Copy in bashrc. Install Brew. Install pyenv. Add ssh key to GitHub. Clone website.
Install emacs. Configure git. Commit this snippet.
Set up virtualenvwrapper.
Clone supervisor config. Sublime Package Manager. INI syntax highlighting.
Map shift-delete, option-delete, and ctrl-delete in Terminal to \027, \027, \033\177 respectively.&lt;/p&gt;
&lt;h3 id=&#34;4-personal-projects&#34;&gt;4. Personal projects&lt;/h3&gt;
&lt;p&gt;Install supervisor. Clone personal projects (snippet-publisher, messager, fb-chat-spreadsheet-updater, cloudbrowser, distraction_detection, kangaroo-auto-responder, private-bieber-twitter, screencapture, local-python-libraries). Install requirements. Install jupyter.&lt;/p&gt;
&lt;p&gt;Note: brew install leveldb before pip install plyvel. brew install redis. Download Hugo. brew install node. brew install postgres.
npm install &amp;ndash;save-dev babel-cli. npm install -g parcel-bundler. npm audit fix. Hugo assets may need permission changes. pip install psycopg2-binary. Run python setup.py develop in messenger/, local-python-libraries/.
Copy messager settings.

&lt;a href=&#34;https://github.com/fbchat-dev/fbchat/issues/615&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Modify fbchat source&lt;/a&gt;.
Log into messager.
Install Docker.&lt;/p&gt;
&lt;p&gt;Start supervisor.&lt;/p&gt;
&lt;h3 id=&#34;5-it-continues&#34;&gt;5. It continues&lt;/h3&gt;
&lt;p&gt;Arrange displays. Install gcloud (brew install &amp;ndash;cask google-cloud-sdk). Install Browserflow.
Set up Ferdi. Set screenshot directory.&lt;/p&gt;
&lt;p&gt;LGTM.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Why do table tennis strokes end at the forehead?</title>
      <link>https://davidbieber.com/snippets/2021-07-10-forehand-to-forehead/</link>
      <pubDate>Sat, 10 Jul 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-07-10-forehand-to-forehead/</guid>
      
      <description>&lt;p&gt;In a table tennis forehand, the stroke typically ends at the forehead. The full stroke is a bit like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Stance&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;The ball is coming toward your forehand side; get in position early.&lt;/li&gt;
&lt;li&gt;Your body is angled slightly to the right, e.g. forming a 15 degree angle between the back edge of the table and the line through your shoulders.&lt;/li&gt;
&lt;li&gt;Your elbow is bent at 90 degree.&lt;/li&gt;
&lt;li&gt;Your wrist is straight, so the paddle forms an extension of the arm.&lt;/li&gt;
&lt;li&gt;Your knees are bent, butt out. You&amp;rsquo;re low to the table, at my height almost squatting.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Ball incoming&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;As the ball approaches there&amp;rsquo;s a small setup phase, where you take the paddle back, and twist to your right a little to allow for a more explosive shot.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;Stroke&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Soon after the ball bounces, say at the peak of the bounce or earlier, you move the paddle through the path of the ball toward where you want to take the ball.&lt;/li&gt;
&lt;li&gt;Your torso rotates the same direction as your arm and paddle. The three have very little relative motion.&lt;/li&gt;
&lt;li&gt;Your weight shifts forward at the same time.&lt;/li&gt;
&lt;li&gt;You can accelerate your paddle during contact with the ball for a more powerful shot.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;Follow through&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;As you follow through the ball, your racket moves near your forehead.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When I, a new player, take a forehand shot, my racket often lands near my chest, not my forehead. This feels more natural. Why is it better to move near the forehead than the chest, and how do you achieve this?&lt;/p&gt;
&lt;h3 id=&#34;reason-1-lower-to-the-table-is-better&#34;&gt;Reason 1: Lower to the table is better&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s better to be low to the table. Being low to the table lets you see the spin better, and gives more arm and leg mobility. It takes more energy though, being in a squat position. Too low, and the mobility decreases.
When you&amp;rsquo;re higher, the follow through to a forehand is more likely to land at your chest, whereas when you&amp;rsquo;re lower, it&amp;rsquo;s going to naturally be closer to your forehead.&lt;/p&gt;
&lt;h3 id=&#34;reason-2-each-stroke-should-prepare-for-the-next-stroke&#34;&gt;Reason 2: Each stroke should prepare for the next stroke&lt;/h3&gt;
&lt;p&gt;A mistake I make is to take a stroke and then bring the paddle back along roughly the same path of the stroke in reverse. Instead, it is faster to make strokes in a circular pattern. Hit through the ball, and continue hitting in an egg-shape pattern until your paddle is back where it started ready for the next stroke. This reduces the need to decelerate the paddle and re-accelerate in the opposite direction. On the other hand, when this isn&amp;rsquo;t practiced so that it&amp;rsquo;s second nature, this consumes extra concentration.&lt;/p&gt;
&lt;p&gt;The forehead might be a natural place on the path toward setting up the next stroke. I&amp;rsquo;m not sure about this one. To me, the chest seems just as viable.&lt;/p&gt;
&lt;h3 id=&#34;reason-3-dont-cut-the-stroke-short&#34;&gt;Reason 3: Don&amp;rsquo;t cut the stroke short&lt;/h3&gt;
&lt;p&gt;To get maximum power and control, you want to hit the ball toward a particular spot on the table. You want to follow through toward that spot, so that you&amp;rsquo;re hitting in the desired direction for the entire contact with the ball. If you cut the stroke short, aka &amp;ldquo;shorting the stroke&amp;rdquo;, you&amp;rsquo;ll impart some side-spin on the ball but won&amp;rsquo;t get maximum power or control.
I guess it works out that moving from the stroke earlier shorts the stroke and ends with the paddle at chest height, but doing a full stroke ends with the paddle at forehead height. This is because the forehand should be moving forward and up through the path of the ball, and a longer time moving up takes you closer to forehead height.&lt;/p&gt;
&lt;p&gt;You don&amp;rsquo;t want to move too far forward and up though. That would leave you with the paddle over the table and your elbow extended, unprepared for the next shot.&lt;/p&gt;
&lt;h3 id=&#34;reason-4-balance-many-concerns&#34;&gt;Reason 4: Balance many concerns&lt;/h3&gt;
&lt;p&gt;Ultimately we want to balance all of these concerns:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Staying low to the table&lt;/li&gt;
&lt;li&gt;Hitting up and forward through the path of the ball&lt;/li&gt;
&lt;li&gt;Hitting toward the target location&lt;/li&gt;
&lt;li&gt;Keeping our balance&lt;/li&gt;
&lt;li&gt;Preparing early for the next shot&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Collectively, this leads to the classic table tennis shot, landing with a forehead height follow through and quick recovery.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Keeping my phone in the kitchen</title>
      <link>https://davidbieber.com/snippets/2021-07-08-phone-in-kitchen/</link>
      <pubDate>Thu, 08 Jul 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-07-08-phone-in-kitchen/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;ve decided to keep my phone in the kitchen while I&amp;rsquo;m in the house.
The goal is to reduce scrolling in the morning and evening, and prevent distractions more generally.
By keeping the phone in the kitchen, I&amp;rsquo;ll be unable to scroll mindlessly when I first wake up (unless of course I go to the kitchen to do so).&lt;/p&gt;
&lt;p&gt;Hopefully by putting this intention up on my website, by having it in writing, by leaving it in a place where others could theoretically have read it, I am more likely to stick to this intention (both the spirit and the letter of it) for a longer period of time.&lt;/p&gt;
&lt;p&gt;Since I don&amp;rsquo;t yet know how this will go, or when I&amp;rsquo;ll first forget about it, I&amp;rsquo;ll pick a date now to check in on it. August 19, 2021. On August 19, 2021, six weeks from today, I&amp;rsquo;ll reevaluate this decision. If I like it, probably I will recommit to it for an additional period of time. If it wasn&amp;rsquo;t working for me, no harm done.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Assorted Laptop Price Comparisons</title>
      <link>https://davidbieber.com/snippets/2021-07-06-laptop-prices/</link>
      <pubDate>Tue, 06 Jul 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-07-06-laptop-prices/</guid>
      
      <description>&lt;p&gt;A 16 GB 13‑inch MacBook Pro costs $1400.&lt;/p&gt;
&lt;p&gt;A 4 GB ASUS Chromebook costs $300.&lt;/p&gt;
&lt;p&gt;An 8 GB 14-inch ThinkPad T14 costs $1300.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;For a 16 GB Chromebook, the Google Pixelbook Go costs $1000.&lt;/p&gt;
&lt;p&gt;For a 16 GB ThinkPad, Lenovo charges $1600.&lt;/p&gt;
&lt;p&gt;For a 64 GB 16-inch MacBook Pro, Apple charges $3000.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Just a little snapshot of the laptop world&amp;rsquo;s prices these days.
Soon we&amp;rsquo;ll see what tomorrow brings.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Reconstructing RL table tennis points in VR</title>
      <link>https://davidbieber.com/snippets/2021-07-03-reconstructing-rl-tt-in-vr/</link>
      <pubDate>Sat, 03 Jul 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-07-03-reconstructing-rl-tt-in-vr/</guid>
      
      <description>&lt;p&gt;
&lt;a href=&#34;https://alexttbarcelona.wixsite.com/home&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&amp;ldquo;Alex TT Barcelona&amp;rdquo;&lt;/a&gt; makes table tennis drills for Eleven Table Tennis.
In a recently released batch of drills, he took a point played by table tennis pro Mima Ito and reconstructed it in VR. The ball machine would &amp;ndash; endlessly in a loop &amp;ndash; play the role of Mima Ito&amp;rsquo;s opponent. It would launch ping pong balls from the same location and with the same trajectory that Mima Ito&amp;rsquo;s opponent hit the ball during the point.&lt;/p&gt;
&lt;p&gt;The reconstruction is a great experience; it really demonstrates the level of play, showcasing how fast and wide the ball goes during professional matches. It also highlights the potential of Eleven Table Tennis as a practice tool for real table tennis. You can reconstruct points from your own real-life table tennis matches in virtual reality, and practice them as many times as you like.&lt;/p&gt;
&lt;p&gt;Today, the process of reconstructing a point from real life in VR is a bit slow and specialized. The way to do it is to open Eleven Table Tennis on a PC (which I don&amp;rsquo;t currently have, making this difficult), and to adjust the ball machine settings on your computer in order to replicate each of your opponent&amp;rsquo;s ball trajectories consecutively.
Once a full point is done, you can play against the ball machine in VR to practice.&lt;/p&gt;
&lt;p&gt;At my last table tennis tournament, I took some footage of myself playing (and losing) a real table tennis match.
I haven&amp;rsquo;t yet tried transcribing it to VR, in part because I don&amp;rsquo;t have a PC. Soon though I hope to transcribe some points so I can practice the shots I&amp;rsquo;m weakest against.&lt;/p&gt;
&lt;p&gt;I estimate that reconstructing a single shot, once you&amp;rsquo;re practiced in the art of table tennis point transcription, takes about a minute. This means that transcribing a full 5-game match, which might have as many as 300-500 individual shots, could take 5-8 hours.&lt;/p&gt;
&lt;p&gt;There are several ways to bring this time down. First, and simplest, is to merely transcribe a subset of the points. Only transcribing shots by your opponent immediately cuts the time in half, and you probably only will want to replay perhaps 10 points total anyway, further cutting down the reconstruction time drastically. Outsourcing the reconstruction to e.g. Fiverr seems plausible, but that doesn&amp;rsquo;t save time overall, it merely pushes the time cost onto someone else.&lt;/p&gt;
&lt;p&gt;Perhaps there&amp;rsquo;s a way to automate the transcription process. 
&lt;a href=&#34;https://stupaanalytics.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Stupa Analytics&lt;/a&gt; uses AI to analyze table tennis matches to provide coaching to players. It seems likely that they model the trajectory of table tennis balls as part of this analysis. Their software works using video from a single phone camera, which is ideal if it works. Perhaps we can build on top of their existing vision systems. I&amp;rsquo;ve reached out to them to inquire, but have not heard back. I&amp;rsquo;ve also tried to use their software, which promised me analysis within 72 hours, but a week later it has still not delivered.&lt;/p&gt;
&lt;p&gt;Some projects on GitHub also show promise for enabling automated transcription. 
&lt;a href=&#34;https://github.com/ckjellson/tt_tracker&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;ckjellson/tt_tracker&lt;/a&gt; uses OpenCV to track table tennis balls using two camera inputs. 
&lt;a href=&#34;https://github.com/vmarquet/table-tennis-computer-vision&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;vmarquet/table-tennis-computer-vision&lt;/a&gt; also offers ball tracking for table tennis using OpenCV, though may require specialized sensors (not clear yet). 
&lt;a href=&#34;https://github.com/maudzung/TTNet-Real-time-Analysis-System-for-Table-Tennis-Pytorch&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;maudzung/TTNet-Real-time-Analysis-System-for-Table-Tennis-Pytorch&lt;/a&gt; uses machine learning to analyze table tennis footage, including ball tracking. These three seem the most promising. Though I don&amp;rsquo;t have any two camera input data currently, I look forward to trying out these projects and seeing if I can repurpose one for RL-to-VR point reconstruction.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Resuming habits</title>
      <link>https://davidbieber.com/snippets/2021-06-23-resuming-habits/</link>
      <pubDate>Wed, 23 Jun 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-06-23-resuming-habits/</guid>
      
      <description>&lt;p&gt;On 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-06-17-a-torrent-of-snippets/&#34;&gt;Thursday&lt;/a&gt; I said I&amp;rsquo;d resume my “Snippets” and the “After Work Activities” habits today.
So, here I am, resuming.&lt;/p&gt;
&lt;p&gt;Still aiming to sleep by 10:10 tonight though, so not too much to say right now.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Serving in table tennis</title>
      <link>https://davidbieber.com/snippets/2021-06-21-serving-in-table-tennis/</link>
      <pubDate>Mon, 21 Jun 2021 02:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-06-21-serving-in-table-tennis/</guid>
      
      <description>&lt;p&gt;We have a couple serves:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The forehand backspin serve&lt;/li&gt;
&lt;li&gt;The disguised left- and right-spin with a little topspin serves&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The key attributes in a serve are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Where it goes&lt;/li&gt;
&lt;li&gt;How fast it goes&lt;/li&gt;
&lt;li&gt;Whether it reaches the back edge&lt;/li&gt;
&lt;li&gt;The spin&lt;/li&gt;
&lt;li&gt;And the perceived depth and spin&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ve read you should always serve to the front or back third of the opponents side, never to the middle third. The reason for preferring these regions is to force the opponent into a less comfortable stroke and maybe put them a bit off balance, as hitting the middle third gives them precisely the stroke they&amp;rsquo;ve most practiced for.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Serve essentials.&lt;/em&gt; You must start the serve above the surface of the table. Does ETT check for this? (A: Yes, but not properly.)
You don&amp;rsquo;t need to be in the left and right lines, and so it can be useful to move to the corner to start a serve. If you do this, get into position right away after serving.&lt;/p&gt;
&lt;p&gt;The toss must be 6 inches or more. A higher toss can give you more speed and spin.
The high toss means you contact the ball with high downward velocity, and greater overall momentum. Most of the momentum on the ball after the serve will come from the paddle, not the toss, so this doesn&amp;rsquo;t seem super critical, but it does add something.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Responding to side-spin</title>
      <link>https://davidbieber.com/snippets/2021-06-21-responding-to-side-spin/</link>
      <pubDate>Mon, 21 Jun 2021 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-06-21-responding-to-side-spin/</guid>
      
      <description>&lt;p&gt;If the server moves their paddle from your left top right across the ball, then add the ball cones toward you its trajectory will bend to your left. You&amp;rsquo;ll want to hit it further left, otherwise it will bounce off your racket to the right and go out.&lt;/p&gt;
&lt;p&gt;How best to think about this?
The ball is spinning to your left; that&amp;rsquo;s why the trajectory bends to your left. By &amp;ldquo;spinning to your left&amp;rdquo;, I refer to the direction the part of the ball leading the trajectory is moving in. Since the ball&amp;rsquo;s coming toward you, it&amp;rsquo;s the part of the ball closest to you that is moving left; the part furthest from you is moving to your right. The Magnus effect cause the trajectory to bend in the direction that leading edge of the ball is traveling in.&lt;/p&gt;
&lt;p&gt;This is why topspin balls fall faster and backspin balls float.
When you hit a topspin ball, the leading part of the ball (furthest from you) is moving down. In a backspin shot the leading part of the ball is moving up.&lt;/p&gt;
&lt;p&gt;When the side-spin ball bounces on the table, it can bounce to the left. When it bounces off your racket, however, it will move to the right. The same spin that&amp;rsquo;s left-spin when coming toward you is right-spin when moving away from you. It isn&amp;rsquo;t that the spin reversed. The spin stayed the same; just the ball&amp;rsquo;s direction reversed. The leading edge is now the one furthest from you. The part of the ball that contacted the paddle was moving left, so it pushed the paddle left and itself right. Now as it moves away it has right-spin on it and the leading edge of the ball in its new trajectory is moving to the right.&lt;/p&gt;
&lt;p&gt;This suggests a difficult but powerful attack. Send a fast left-spin ball (by moving your paddle to the right) down the right side of the table. When your opponent goes to return it, the default behavior will be for it to bounce to your right, their left, further off the right edge of the table.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Backhand flicks, drives, loops, and pushes</title>
      <link>https://davidbieber.com/snippets/2021-06-21-backhand-flicks-drives-loops-and-pushes/</link>
      <pubDate>Mon, 21 Jun 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-06-21-backhand-flicks-drives-loops-and-pushes/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;Note for potential reader: I&amp;rsquo;m new to this sport, and my commentary might not be correct or good advice :).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s the difference between backhand flicks, drives, loops, and pushes?&lt;/p&gt;
&lt;p&gt;Flicks, drives, and loops all impart topspin on the ball. The backhand push typically imparts backspin.&lt;/p&gt;
&lt;p&gt;The drive is more of a forward motion, giving a flatter resulting ball compared with the heavier topspin of a flick or loop. A backhand drive done well might result in a flat ball entirely, rather than a topspin one.&lt;/p&gt;
&lt;p&gt;The backhand flick and loop might actually refer to the same stroke, I&amp;rsquo;m not sure. I&amp;rsquo;ll say what I think the differences are. The backhand flick uses very heavy wrist to get topspin, while the loop drives is topspin more from forward motion of the paddle, both brushing the top of the ball to import heavy topspin.&lt;/p&gt;
&lt;p&gt;In both cases (in all cases, really) it&amp;rsquo;s important to keep the wrist (and shoulder) relaxed, forming up most (but only a little) at the time of making contact with the ball. Remaining relaxed allows you to adjust strokes more quickly. This allows handling unexpected ball placements and decisions from the expected spin and bounce more gracefully.&lt;/p&gt;
&lt;p&gt;Classical advice suggests you should not reach (extending your elbow) so that you can always use the same shot, and so you have more control over the angle of your paddle. Instead of reaching, the advice goes, you should move your feet so you&amp;rsquo;re in position to hit the ball. This advice can be misleading; it&amp;rsquo;s silly to avoid reaching when reaching is necessary, and it&amp;rsquo;s bad advice to avoid learning a useful stroke. It&amp;rsquo;s good advice to use your feet. And above all, it&amp;rsquo;s a good observation that reaching can be a common failure mode for the backhand strokes.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also true that when this failure mode arises it can be naturally accompanied by pointing the racket face in slightly the wrong direction.&lt;/p&gt;
&lt;p&gt;The primary ways to counter this are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;practicing footwork to get into place&lt;/li&gt;
&lt;li&gt;experience so if you have to reach you get the angle right&lt;/li&gt;
&lt;li&gt;awareness of the pitfall so you can notice it and adjust more rapidly&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A bad thing to do would be to avoid reaching when reaching is necessary.&lt;/p&gt;
&lt;p&gt;Another piece of advice is to avoid reaching forward. This advice is similar to that above about reaching left on backhands. You can put your leg under the table to minimize your reach, but ultimately reaching is necessary for retrieving drop shots and other short shots. The right takeaway is that footwork comes first, not that racing should be avoided.&lt;/p&gt;
&lt;p&gt;It often gets repeated that the reason to avoid reaching is so you can reuse your strokes. This seems like you&amp;rsquo;re setting yourself up for failure. To succeed in unexpected situations you need to know exactly how your paddle behaves no matter how you&amp;rsquo;re hitting it. You don&amp;rsquo;t want to just be memorizing a small number of strokes and applying them as best as possible in whatever situation arises. If you do that, your game-play will be so fragile. It won&amp;rsquo;t work if the ball&amp;rsquo;s a little too high, too low, or too wide. Better to practice both the core strokes, the necessary footwork, AND how to use your strokes at their extreme values for when footwork and reflexes are insufficient to bring the ball into a standard position.
Is this right?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Can I put a spreadsheet into Ferdi?</title>
      <link>https://davidbieber.com/snippets/2021-06-17-spreadsheet-in-ferdi/</link>
      <pubDate>Thu, 17 Jun 2021 04:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-06-17-spreadsheet-in-ferdi/</guid>
      
      <description>&lt;p&gt;Can I put a spreadsheet into Ferdi? I don&amp;rsquo;t see why not. I think if it works well I would want to put my After Work Activities and Automatic Transaction Log spreadsheets into Ferdi so they&amp;rsquo;re always available at my fingertips.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s silly that Chrome doesn&amp;rsquo;t offer tab freezing. Maybe it does. Ferdi&amp;rsquo;s hibernation seems less memory hungry than having extra tabs open in Chrome, but perhaps this is wrong. Chrome doesn&amp;rsquo;t really handle special keyboard-shortcut bound tabs organization super well anyway though. The new cmd-option-a search tabs feature is nice though. Maybe that can let me move some tabs to chrome instead of Ferdi.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A torrent of snippets!</title>
      <link>https://davidbieber.com/snippets/2021-06-17-a-torrent-of-snippets/</link>
      <pubDate>Thu, 17 Jun 2021 03:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-06-17-a-torrent-of-snippets/</guid>
      
      <description>&lt;p&gt;A torrent of snippets!&lt;/p&gt;
&lt;p&gt;The reason I&amp;rsquo;m putting out four snippets all at once is I have time to relax on this plane to Austin. The reason I haven&amp;rsquo;t been writing snippets in the month leading up to this&amp;hellip; I think I was shaken from the habit by the NeurIPS deadline, and then didn&amp;rsquo;t take the habit back up after the deadline passed.&lt;/p&gt;
&lt;p&gt;I find this pattern recurring, and I remember I was already aware of it at least as far back as 2013. The pattern is: I develop a habit, I am diligent at keeping that habit until it&amp;rsquo;s broken by some event (usually travel), and then I&amp;rsquo;m slow to take the habit back up if I do at all after the perturbation has subsided. In this case, travel is actually the thing leading me to pick the snippets habit back up, rather than the thing to break the habit (although perhaps my snippets-stopping did correspond to a travel time; I&amp;rsquo;d need to look at a calendar to double check.)&lt;/p&gt;
&lt;p&gt;Anyhow, noticing this pattern suggests a way to combat it, to keep habits through these perturbations. It will require some diligence, but I think the trick is to anticipate the perturbation and make a plan to reignite the habit after its conclusion. For example, if I&amp;rsquo;m traveling for a weekend, I could schedule an email to myself saying &amp;ldquo;resume habit X&amp;rdquo; to be delivered a couple days after I get back from my travels, when I expect the perturbation to have fully passed.&lt;/p&gt;
&lt;p&gt;I think I&amp;rsquo;ll leave a message for my future self here and now, for next Wednesday:
David, on Wednesday June 23, resume the &amp;ldquo;Snippets&amp;rdquo; and the &amp;ldquo;After Work Activities&amp;rdquo; habits.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Areas of table tennis to improve at</title>
      <link>https://davidbieber.com/snippets/2021-06-17-areas-of-table-tennis-to-improve-at/</link>
      <pubDate>Thu, 17 Jun 2021 02:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-06-17-areas-of-table-tennis-to-improve-at/</guid>
      
      <description>&lt;p&gt;Right now the biggest area to work on is having the confidence (and skill) to attack in a match setting.&lt;/p&gt;
&lt;p&gt;I have this confidence in Eleven Table Tennis (ETT), usually, but in the real world its harder to demonstrate.
I guess I become conservative in the real world because you have to be responsible for your balls.
In ETT you can try an aggressive shot and if it goes into the stands or out the window, no big deal. In practice starting aggressive doesn&amp;rsquo;t go so wildly. Still, in ETT you can feed dozens of balls quickly in order to develop the proper feel.&lt;/p&gt;
&lt;p&gt;I think that&amp;rsquo;s a solid idea to bring into the real world. I&amp;rsquo;ll buy 50+ practice balls and then I can serve a bunch real quickly or multi ball with a partner in order to develop that feel more quickly in the real world.&lt;/p&gt;
&lt;p&gt;The main areas I want to get good feel for quickly in the real world are backhand flicks and forehand topspin drives.&lt;/p&gt;
&lt;p&gt;Some of the tips I&amp;rsquo;ve picked up in my month of playing for the backhand flicks are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Follow the ball with your core&lt;/li&gt;
&lt;li&gt;You don&amp;rsquo;t want to be reaching too much for the ball; you want to reuse the same stroke as much as possible each time.&lt;/li&gt;
&lt;li&gt;Use shoulder, wrist, and a little torso, I think in that order. A basic shot would be mostly shoulder. For a more attacking show, a proper flick, add in a lot of wrist. Finally for max power, add a tiny bit of torso. And you should use leg power too.&lt;/li&gt;
&lt;li&gt;Left foot beyond the edge of the table, closer to the table than the right foot&lt;/li&gt;
&lt;li&gt;Relaxed wrist&lt;/li&gt;
&lt;li&gt;Watch the ball all the way in&lt;/li&gt;
&lt;li&gt;Hit the top of the ball, say 2/3 of the way up&lt;/li&gt;
&lt;li&gt;Practice! Have a plan when starting the point. Always be ready to third ball attack when serving.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;How about tips for the forehand drive?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Move early into position&lt;/li&gt;
&lt;li&gt;Again the goal is to use the same stroke each time&lt;/li&gt;
&lt;li&gt;As before shoulder, wrist, and torso are key.
Wow, despite looking so different the tips are remarkably similar to the backhand flick&lt;/li&gt;
&lt;li&gt;Watch the ball all the way in&lt;/li&gt;
&lt;li&gt;Brush up the ball&lt;/li&gt;
&lt;li&gt;Your stroke ends in front of your face&lt;/li&gt;
&lt;li&gt;And your wrist points forward from your forearm, not up&lt;/li&gt;
&lt;li&gt;And I think the squat is perhaps a bit reduced compared with the backhand flick&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Browserflow is live!</title>
      <link>https://davidbieber.com/snippets/2021-06-17-browserflow-is-live/</link>
      <pubDate>Thu, 17 Jun 2021 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-06-17-browserflow-is-live/</guid>
      
      <description>&lt;p&gt;Browserflow is live! Beyond exciting!&lt;/p&gt;
&lt;p&gt;Congratulations to DK on the launch. For those not familiar, Browserflow is a simple low/no-code browser automation chrome extension that DK&amp;rsquo;s been diligently working on for over a year (read his journey over at 
&lt;a href=&#34;https://roadtoramen.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;roadtoramen.com&lt;/a&gt;; he&amp;rsquo;s an excellent writer!). You can automate anything in the browser with it, and it comes with a nice typeahead for launching flows from anywhere, as well as a Browserflow Cloud service that lets you schedule your flows to run in the cloud.&lt;/p&gt;
&lt;p&gt;My favorite use cases for Browserflow are note-taking. Run a flow and then everything you highlight gets copied into Roam. Change the flow a little, and you can use keyboard shortcuts to control how the notes get organized.&lt;/p&gt;
&lt;p&gt;Other people use flows for scraping info off Twitter, or lead generation, or monitoring stock prices. It&amp;rsquo;s a super general purpose tool. There are so many things you can do with it; it really has so much potential.&lt;/p&gt;
&lt;p&gt;Web scraping and browser automation aren&amp;rsquo;t new of course, so what makes Browserflow special? It&amp;rsquo;s got craftsmanship. Browserflow is super easy to use, and it feels good to use all the while. DK has really paid close attention to the details to make it work well.&lt;/p&gt;
&lt;p&gt;Take scraping Twitter, for example. In Browserflow, writing a for loop over all the Tweets on a timeline is trivial. If you were to attempt that with an alternative like Tampermonkey or Selenium, it would be considerably more difficult. You&amp;rsquo;d need to think about how the DOM is changing as you scroll, and which tweets you&amp;rsquo;ve already considered. Browserflow takes care of the details for you so you can focus on writing the logic that matters to you.&lt;/p&gt;
&lt;p&gt;Give it a try today at 
&lt;a href=&#34;https://browserflow.app/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;browserflow.app&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>How to qualify for the US Olympic table tennis team</title>
      <link>https://davidbieber.com/snippets/2021-06-17-table-tennis-olympic-qualifiers/</link>
      <pubDate>Thu, 17 Jun 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-06-17-table-tennis-olympic-qualifiers/</guid>
      
      <description>&lt;p&gt;How to qualify for the US Olympic table tennis team.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Become the best singles table tennis player in the country, preferably by a significant margin&lt;/li&gt;
&lt;li&gt;Enter the qualifiers&lt;/li&gt;
&lt;li&gt;Win the qualifiers&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is far more straightforward than I would have expected. Obviously step 1 presents a significant challenge, and step 2 probably involves some paperwork. Still, it came as a shock to me that a single tournament, open to any USATT player as far as I can tell, which only gets 50 entrants, is all that stands between an aspirational table tennis player and such a significant event as the Olympics.&lt;/p&gt;
&lt;p&gt;On to step 1!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>You Have 30 Days to Request a Review</title>
      <link>https://davidbieber.com/snippets/2021-05-19-thirty-days-to-request-a-review/</link>
      <pubDate>Wed, 19 May 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-05-19-thirty-days-to-request-a-review/</guid>
      
      <description>&lt;p&gt;Today I received an unexpected email from Facebook. Subject: &amp;ldquo;Action needed on your Facebook account&amp;rdquo;. It starts: &amp;ldquo;You Have 30 Days to Request a Review&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;The email read:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-md&#34;&gt;Hi David,
Your Facebook account has been disabled. This is because your account, or activity on it, doesn&#39;t follow our Community Standards.

If you think we disabled your account by mistake, we can take you through a few steps to request a review. You&#39;ll need to complete these steps within 30 days to avoid your account being permanently disabled.

You can learn more about why we sometimes disable accounts by visiting the Community Standards.
 
Thanks,
The Facebook Security Team
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There was a large blue button &amp;ldquo;Request Review&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;I have no idea why my account was disabled. There was no indication in the email. I don&amp;rsquo;t really use Facebook proper much &amp;ndash; do the Community Standards require that I use Facebook more? No, that would be absurd. I do use Messenger quite a bit. I have a Messenger bot, Bieber Bot. Did Bieber Bot violate some Bot guidelines? I don&amp;rsquo;t think so. Outside of Messenger my only Facebook activity is coordinating table tennis matches with strangers.&lt;/p&gt;
&lt;p&gt;I clicked &amp;ldquo;Request Review&amp;rdquo;. The system says it wants to confirm my identity. There&amp;rsquo;s a grayed out &amp;ldquo;Continue&amp;rdquo; button but no way to click it. After a few minutes of trying to figure out how to click the button, I switch to Firefox. In Firefox the screen looks a bit different: there&amp;rsquo;s a &amp;ldquo;Prove your not a robot&amp;rdquo; checkbox for me to click. I couldn&amp;rsquo;t see it when I was in Chrome, but now that I&amp;rsquo;m in Firefox the checkbox is visible.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d never quite understood how a single checkbox can prove I&amp;rsquo;m not a robot. It didn&amp;rsquo;t make sense. A robot can check a box just as well as anyone, or so I thought. Maybe Google looks at timing data or the location of your mouse, or other properties of your browser, and predicts if you&amp;rsquo;re a robot from that. Now I understand &amp;ndash; I couldn&amp;rsquo;t see the checkbox when I was in Chrome. &lt;em&gt;I&lt;/em&gt; was the robot! Robots simply can&amp;rsquo;t see that checkbox. By switching to Firefox I restored my humanity. I checked the box and proceeded.&lt;/p&gt;
&lt;p&gt;The review lasted all of 100ms. After proving my humanity and initiating the review of my account for satisfaction of the Community Standards, my account was immediately restored. I&amp;rsquo;m grateful for this, since I rely on Bieber Bot and Messenger quite heavily.&lt;/p&gt;
&lt;p&gt;Glad I thought to try Firefox. I didn&amp;rsquo;t see any way to move forward otherwise. With my account restored, I can now resume my day.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Writing in the woods</title>
      <link>https://davidbieber.com/snippets/2021-05-16-writing-in-the-woods/</link>
      <pubDate>Sun, 16 May 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-05-16-writing-in-the-woods/</guid>
      
      <description>&lt;p&gt;Remember, David, you&amp;rsquo;re only writing for yourself. Not even that, actually; you&amp;rsquo;re writing for no audience. This isn&amp;rsquo;t meant to be read by anyone. So, don&amp;rsquo;t worry about your word choice, or whether to call it &amp;ldquo;word choice&amp;rdquo; or &amp;ldquo;diction&amp;rdquo;. Just get words on paper and get going.&lt;/p&gt;
&lt;p&gt;This is a snippet about writing in the woods. I haven&amp;rsquo;t solved it. I&amp;rsquo;ll start by explaining some of the problems that come up when you (I) set out to write in the woods. They aren&amp;rsquo;t &amp;ldquo;problems&amp;rdquo; so much as ideas for quality of life improvements, but again, the word choice isn&amp;rsquo;t important.&lt;/p&gt;
&lt;h2 id=&#34;qol-idea-1-a-surface-for-the-keyboard&#34;&gt;QOL Idea 1: A surface for the keyboard&lt;/h2&gt;
&lt;p&gt;When I find a nice place to sit &amp;ndash; one that won&amp;rsquo;t leave my butt wet, overly dirty, or otherwise too uncomfortable &amp;ndash; there is rarely a clear place for my keyboard. (&amp;ldquo;rarely&amp;rdquo; == &amp;ldquo;If there&amp;rsquo;s a picnic table, then there is, but otherwise there is not.&amp;quot;) Most often the seat I find is a stone or a tree trunk, and the most natural places to put the keyboard are: (1) on my lap, or (2) to my side, on the trunk or stone.&lt;/p&gt;
&lt;p&gt;These methods work. I can write. I enjoy it immensely. However, neither is ideal. One leaves the keyboard unsteady and thereby slows typing, the other cranes my neck. Perhaps bringing a board to place on my lap could solve the problem. I know lap desks are a thing; I don&amp;rsquo;t know if they pack well for hiking. I don&amp;rsquo;t need something the full size of a 
&lt;a href=&#34;https://www.amazon.com/LapGear-Essential-Lap-Desk-Charcoal/dp/B076DRYBM2&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;lap desk&lt;/a&gt; though; a simple 4&amp;rdquo; x 12&amp;quot; stiff piece of material would likely be sufficient to provide the keyboard some rigidity. The keyboard I use folds in half, and can buckle in the middle while I type if not on a surface that supports it. Alternatively to the stiff material, I could find a keyboard that doesn&amp;rsquo;t have this buckling issue. It would be larger than the current keyboard, but not larger than the keyboard plus stiff material. Perhaps something 
&lt;a href=&#34;https://www.amazon.com/Anker-Bluetooth-Ultra-Slim-Keyboard-Devices/dp/B0096M8VR2/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;like this&lt;/a&gt;. It&amp;rsquo;s larger than 
&lt;a href=&#34;https://www.amazon.com/gp/product/B06XSQS7ZP&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;my current foldable keyboard&lt;/a&gt; but shouldn&amp;rsquo;t have the buckling issue, and so may do well just placed in my lap.&lt;/p&gt;
&lt;p&gt;Another advantage of my current keyboard is the case doubles as a stand for my phone, so I can see what I&amp;rsquo;m typing. I don&amp;rsquo;t &lt;em&gt;strictly&lt;/em&gt; need to see what I&amp;rsquo;m typing as I type it, but occasionally it is useful and I wouldn&amp;rsquo;t want to give that up unless it really enhanced the convenience of the setup.&lt;/p&gt;
&lt;h2 id=&#34;qol-idea-2-more-seat-selection&#34;&gt;QOL Idea 2: More seat selection&lt;/h2&gt;
&lt;p&gt;As I&amp;rsquo;m wandering in the woods I sometimes go quite a while before finding a place that looks like a good seat. As I&amp;rsquo;ve become more familiar with Guilford&amp;rsquo;s Westwoods, I&amp;rsquo;ve noticed decent tree trunks and stones more often. Sometimes they&amp;rsquo;re covered in brush though. It would be nice to be able to find a seat somewhat quickly once I reach a nice part of the woods.&lt;/p&gt;
&lt;p&gt;I could bring something with me to sit on. One crazy idea is 
&lt;a href=&#34;https://www.youtube.com/watch?v=RVgaRjhqFHs&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;those SkyMall leg-chairs&lt;/a&gt; &amp;ndash; a pair of legs that you wear so you can sit down anywhere&amp;hellip; I&amp;rsquo;m not going to do that; it looks uncomfortable and expensive. I&amp;rsquo;m thinking more along the lines of bringing a waterproof cushion or piece of fabric I can sit, or something to dry wet surfaces. Maybe I should just bring a trash bag to sit on. That would be easy to carry, I can sit on it to make any surface clean, and then after it even doubles as a trash bag.&lt;/p&gt;
&lt;h2 id=&#34;other-qol-ideas&#34;&gt;Other QOL Ideas&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;How can I minimize bug nuisances? A: Bug spray&amp;hellip;&lt;/li&gt;
&lt;li&gt;Can I carry water while keeping my hands free? A: Yes, with a Camelbak.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Lighthouse</title>
      <link>https://davidbieber.com/snippets/2021-05-03-lighthouse/</link>
      <pubDate>Mon, 03 May 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-05-03-lighthouse/</guid>
      
      <description>&lt;p&gt;
&lt;a href=&#34;https://web.dev/measure/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;web.dev&lt;/a&gt; (former known as Lighthouse) is a tool for measuring your website&amp;rsquo;s performance and getting tips for how to improve it. I&amp;rsquo;m in the process of following some of its suggestions right now.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Working session&amp;hellip;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Progress so far:&lt;/p&gt;
&lt;p&gt;One of web.dev&amp;rsquo;s suggestions was to enable gzip compression of the pages on my website.&lt;/p&gt;
&lt;p&gt;Tornado supports this, but only starting at version 4.0 and newer. I&amp;rsquo;m on an older version. So, I&amp;rsquo;d like to upgrade tornado.&lt;/p&gt;
&lt;p&gt;I try to install a newer version of tornado with pip, but I cannot. I receive an InsecurePlatformWarning when I try to do so. I can upgrade to a newer version of Python to solve this, it says.&lt;/p&gt;
&lt;p&gt;I try to install Python 3 with apt-get, but I cannot. dpkg encounters an error during the apt-get install.&lt;/p&gt;
&lt;p&gt;Why? I&amp;rsquo;ll figure that out next time.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Tags on Snippets</title>
      <link>https://davidbieber.com/snippets/2021-05-02-snippet-tags/</link>
      <pubDate>Sun, 02 May 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-05-02-snippet-tags/</guid>
      
      <description>&lt;p&gt;Recently I added tags to my snippets. Today, I updated the 
&lt;a href=&#34;https://davidbieber.com/tags/&#34;&gt;tags page&lt;/a&gt; to display the number of snippets containing the tag. Now I can easily see what topics I write about the most, and which I&amp;rsquo;ve written about only a little. Here&amp;rsquo;s where the counts stand today:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/browserflow/&#34;&gt;browserflow (7)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/table-tennis/&#34;&gt;table tennis (3)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/automatic-video-editing/&#34;&gt;automatic-video-editing (7)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/virtual-reality/&#34;&gt;virtual reality (3)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/roam-research/&#34;&gt;roam-research (19)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/snippets/&#34;&gt;snippets (20)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/tech-tips/&#34;&gt;tech-tips (6)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/python/&#34;&gt;python (16)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/aspirational-intent/&#34;&gt;aspirational-intent (2)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/goals/&#34;&gt;goals (6)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/peer-learning-group/&#34;&gt;peer-learning-group (7)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/attention/&#34;&gt;attention (21)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/taking-silly-ideas-seriously/&#34;&gt;taking-silly-ideas-seriously (23)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/python-fire/&#34;&gt;Python Fire (4)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/javascript/&#34;&gt;javascript (5)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/sql/&#34;&gt;sql (10)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/wisdom/&#34;&gt;wisdom (2)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/browser-history/&#34;&gt;browser-history (10)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/thought-experiments/&#34;&gt;thought-experiments (6)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/spaced-repetition/&#34;&gt;spaced-repetition (3)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/math/&#34;&gt;math (5)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/ask-me-anywhere/&#34;&gt;ask-me-anywhere (2)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/google-apps-script/&#34;&gt;Google Apps Script (3)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/automation/&#34;&gt;Automation (3)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/just-for-fun/&#34;&gt;Just for Fun (3)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/productivity/&#34;&gt;Productivity (4)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/software/&#34;&gt;Software (6)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/hardware/&#34;&gt;Hardware (2)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/puzzle/&#34;&gt;Puzzle (2)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/education/&#34;&gt;Education (6)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/esperanto/&#34;&gt;Esperanto (1)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://davidbieber.com/tags/princeton-acm/&#34;&gt;Princeton ACM (2)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Looking this over, I think I&amp;rsquo;d like to normalize the format of the tags. The ones with capital letters at the end date from before I started snippets; those are the tags I used to categorize the projects on my website. I also see I&amp;rsquo;ve only written about puzzles twice. Perhaps I&amp;rsquo;ll write about puzzles more. Also, why is there no tag to find all snippets about Bieber Bot? I&amp;rsquo;ll have to fix this.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Making a Browserflow Flow for Eleven Table Tennis VR</title>
      <link>https://davidbieber.com/snippets/2021-05-01-table-tennis-flow/</link>
      <pubDate>Sat, 01 May 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-05-01-table-tennis-flow/</guid>
      
      <description>&lt;p&gt;In this snippet I chronicle making a Cloud flow that tracks my progress in Eleven Table Tennis VR, a virtual reality table tennis game I&amp;rsquo;ve been playing a bunch over the last month.&lt;/p&gt;
&lt;p&gt;I took a first pass at making the flow earlier in the week, and ran into two hiccups I&amp;rsquo;ll need to work around: (1) The css selectors for my ELO, Rank, etc change between visits to the website. How am I going to extract this data in the flow? (2) Some games have three rounds others have two, and the css selectors differ depending on which game we&amp;rsquo;re looking at.&lt;/p&gt;
&lt;h2 id=&#34;challenge-1-stable-css-selectors-across-page-loads&#34;&gt;Challenge 1: Stable CSS Selectors Across Page Loads&lt;/h2&gt;
&lt;p&gt;Browserflow&amp;rsquo;s default CSS selector for the ELO rate on 
&lt;a href=&#34;https://www.elevenvr.net/eleven/413682&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;my Eleven TT page&lt;/a&gt; is &lt;code&gt;div:nth-of-type(1) &amp;gt; .jss87 &amp;gt; .MuiTypography-root&lt;/code&gt;. The trouble with this is that the class .jss87 isn&amp;rsquo;t always there. Sometimes when I load the page, the class .jss70 is there instead. I don&amp;rsquo;t know how this class is determined, but it isn&amp;rsquo;t stable enough to use for my flow.&lt;/p&gt;
&lt;p&gt;With a bit of poking around, I was able to use an 
&lt;a href=&#34;https://css-tricks.com/almanac/selectors/n/nth-child/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;nth-child&lt;/code&gt; rule&lt;/a&gt; to write a more stable selector. Here&amp;rsquo;s what I came up with: &lt;code&gt;div.MuiGrid-container &amp;gt; .MuiPaper-root:nth-child(1) .MuiTypography-root&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With this new strategy in place, I can easily complete the first half of the flow (which I&amp;rsquo;ll probably actually split into two flows): regularly logging my Eleven Elo, Rank, Win and Loss count, and Win rate into a spreadsheet automatically.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what the completed flow looks like:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://davidbieber.com/snippets/2021-05-01-table-tennis-flow.png&#34; alt=&#34;Complete table tennis ranking tracker flow&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;challenge-2-varying-css-selectors-across-rows&#34;&gt;Challenge 2: Varying CSS Selectors Across Rows&lt;/h2&gt;
&lt;p&gt;Next up I have the challenge of selecting game data from the 
&lt;a href=&#34;https://www.elevenvr.net/eleven/413682&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;same page&lt;/a&gt;. Browserflow makes it easy to loop over the match data with its Loop Elements command. The trouble is that some matches have three rounds while others have just two.&lt;/p&gt;
&lt;p&gt;The default CSS selects for the game data are e.g. &lt;code&gt;$match tr:nth-of-type(1) &amp;gt; td:nth-of-type(3)&lt;/code&gt; for the Match Score. Two of the columns: &amp;ldquo;ELO +-&amp;rdquo; and &amp;ldquo;Round 3&amp;rdquo; only show up in certain matches. &amp;ldquo;ELO +-&amp;rdquo; only shows up for ranked matches, and &amp;ldquo;Round 3&amp;rdquo; only shows up if the first two matches are split between the players.&lt;/p&gt;
&lt;p&gt;I expect that in rare cases there are matches with only 1 round (e.g. because a player leaves early), and that in the future there might be matches with additional rounds too.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt; elements themselves don&amp;rsquo;t contain any additional information indicating what column they belong to. I might have to take this slightly painstaking approach:&lt;/p&gt;
&lt;p&gt;First, I&amp;rsquo;ll use &lt;code&gt;Get Element Text&lt;/code&gt; to get the text of the first six column headers, and I&amp;rsquo;ll have it use blank text if there are fewer than six headers. In some cases these will be USERNAME, ELO +-, MATCH SCORE, ROUND 1, ROUND 2, ROUND 3. In other cases it will just be a subset of this information.&lt;/p&gt;
&lt;p&gt;Then, for each player I&amp;rsquo;ll get the first six entries in their row. I&amp;rsquo;ll use the headers to determine what these entries describe.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Brief programming interlude&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve done it. Here&amp;rsquo;s the completed flow. It works like a charm.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://davidbieber.com/snippets/2021-05-01-table-tennis-spreadsheet.png&#34; alt=&#34;Complete table tennis games flow with collected data&#34;&gt;&lt;/p&gt;
&lt;p&gt;I had to make 19 &lt;code&gt;Get Element Text&lt;/code&gt; actions and a &lt;code&gt;Run Script&lt;/code&gt;, even though I only needed data from 13 different elements. Collecting tabular data is a pretty common task, so there&amp;rsquo;s room to make this simpler for future flows.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the script I ended up writing for populating fields based on the header data, just for reference:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;let $player1 = $row1field1;
let $player2 = $row2field1;

let $elo1 = &amp;quot;&amp;quot;;
let $elo2 = &amp;quot;&amp;quot;;
let $elo1change = &amp;quot;&amp;quot;;
let $elo2change = &amp;quot;&amp;quot;;
let score_index = 1;

if ($header2 == &amp;quot;ELO +-&amp;quot;) {
  let elo1 = $row1field2;
  let elo2 = $row2field2;
  $elo1 = elo1.split(&amp;quot; &amp;quot;)[0];
  $elo2 = elo2.split(&amp;quot; &amp;quot;)[0];
  let elo1change = elo1.split(&amp;quot; &amp;quot;)[1];
  let elo2change = elo2.split(&amp;quot; &amp;quot;)[1];
  // Remove the parentheses (+16) -&amp;gt; +16.
  $elo1change = elo1change.substring(1, elo1change.length - 1);
  $elo2change = elo2change.substring(1, elo2change.length - 1);
  score_index = 2;
}

var row1fields = [
  $row1field1,
  $row1field2,
  $row1field3,
  $row1field4,
  $row1field5,
  $row1field6,
];
var row2fields = [
  $row2field1,
  $row2field2,
  $row2field3,
  $row2field4,
  $row2field5,
  $row2field6,
];

var $matchscore1 = row1fields[score_index];
var $matchscore2 = row2fields[score_index];
var $round1player1 = row1fields[score_index + 1];
var $round1player2 = row2fields[score_index + 1];
var $round2player1 = row1fields[score_index + 2];
var $round2player2 = row2fields[score_index + 2];
var $round3player1 = row1fields[score_index + 3];
var $round3player2 = row2fields[score_index + 3];

var gameidanddate_parts = $gameidanddate.split(&amp;quot; : &amp;quot;, 2);
let $gameid = gameidanddate_parts[0];
// TODO(dbieber): Parse timestamp.
let $timestamp = gameidanddate_parts[1];

// formatDate definition elided.
let $today = formatDate(new Date());
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;future-challenge-record-every-game-exactly-once&#34;&gt;Future Challenge: Record every game exactly once&lt;/h2&gt;
&lt;p&gt;The current instance of the flow just collects all the games on page 1 into the spreadsheet. What I&amp;rsquo;d really like the flow to do is collect every game once.
My flow will run once a day.&lt;/p&gt;
&lt;p&gt;I could do this by parsing the dates, and having the flow collect all the flows less than one day old each time it runs. This wouldn&amp;rsquo;t be robust to missing a day though.&lt;/p&gt;
&lt;p&gt;Another approach would be to have the flow look in the spreadsheet for the last game collected, and then keep collecting games until that most recently collected game is reached. I&amp;rsquo;ll discuss these options with DK before proceeding. For now, it&amp;rsquo;ll just collect a subset of my games, or collect some games twice if I play fewer than 10 on some day.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;You can find the flows 
&lt;a href=&#34;https://browserflow.app/shared/4a8c4303-ad21-420e-8414-5de57e0692d4&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;here&lt;/a&gt; and 
&lt;a href=&#34;https://browserflow.app/shared/4e3fd160-6665-46b7-ad2b-0a6be9121649&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;here&lt;/a&gt; if you have Browserflow.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Recording in virtual reality (incomplete)</title>
      <link>https://davidbieber.com/snippets/2021-04-29-recording-in-vr/</link>
      <pubDate>Thu, 29 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-04-29-recording-in-vr/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;This is an 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-04-23-incomplete-snippets/&#34;&gt;&lt;strong&gt;incomplete&lt;/strong&gt; snippet&lt;/a&gt;. If I complete it, I&amp;rsquo;ll add a link to the completed snippet here.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The default format for recording in virtual reality is a first-person perspective&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;. Often this is placed side-by-side with a third-person perspective of the person in real life&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;. I would like to see the same perspective of the player in VR and real life&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Recording the same perspective of the player both in-game and in real life makes it easier to mentally translate between the real life movements of the player and their in-game effects. It also enables overlaying the two views for a smooth transition between the two domains. For example, you can split the screen in the middle of the player&amp;rsquo;s body, showing half in the VR domain and half in the real domain.&lt;/p&gt;
&lt;p&gt;This opens up the potential for low friction, minimal fuss streaming controls for streamers to use mid-game. It only takes one button or D-stick dedicated to controlling the camera to let a player toggle between streaming a fully VR perspective, a fully real life perspective, and something in between.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;First-person perspective in VR. &lt;img src=&#34;https://davidbieber.com/snippets/2021-04-29-recording-in-vr-001.png&#34; alt=&#34;First-person perspective.&#34;&gt; &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;TODO(dbieber): Add an image of a third-person perspective in real life of someone using VR. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;TODO(dbieber): Add an image showing the same perspective in VR and real life. &lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>GetSoils.com: A new soil marketplace</title>
      <link>https://davidbieber.com/snippets/2021-04-27-getsoils/</link>
      <pubDate>Tue, 27 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-04-27-getsoils/</guid>
      
      <description>&lt;p&gt;My friend 
&lt;a href=&#34;https://twitter.com/olshansky&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dan Olshansky&lt;/a&gt; recently launched a new company 
&lt;a href=&#34;https://getsoils.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;GetSoils.com&lt;/a&gt;. It&amp;rsquo;s an online marketplace for soil. If you have soil you&amp;rsquo;re looking to get rid of, or are looking to purchase soil, you can use 
&lt;a href=&#34;https://getsoils.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;GetSoils.com&lt;/a&gt; to find a buyer or seller for your soil.&lt;/p&gt;
&lt;p&gt;Since he&amp;rsquo;s launching a new marketplace, it needs buyers and sellers on the site for it to be useful.
The more people buying and selling soil, the more useful his site becomes, and in turn more people will join to buy and sell their soil &amp;ndash; a virtuous cycle, if he can get the word out.&lt;/p&gt;
&lt;p&gt;So, part of why I&amp;rsquo;m writing this snippet is to help him get the word out. The website is (as I&amp;rsquo;ve now stated repeatedly) 
&lt;a href=&#34;https://getsoils.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;GetSoils.com&lt;/a&gt; and if you have soil to buy or sell, I encourage you to give it a try. Posting a listing is free.&lt;/p&gt;
&lt;p&gt;Why use GetSoils over, say, CraigsList? From what I understand, there are a few reasons: (1) GetSoils is a marketplace specifically for soil, so hopefully it&amp;rsquo;s easier to find a buyer or seller there than on a generic site like CraigsList. (2) GetSoils does analysis to reduce soil travel and maximize soil reuse &amp;ndash; thereby benefiting the environment and keeping costs low. (3) GetSoils has expertise in soil, and helps you ensure compliance with government regulations pertaining to soil, and makes filing the necessary reports easy.&lt;/p&gt;
&lt;p&gt;Alright, with the advertising portion of the snippet complete, I&amp;rsquo;ll now take a few minutes to try and understand the soil market a little bit better.&lt;/p&gt;
&lt;p&gt;The website supports buying and selling the following soil types: Sand and Gravel, Sands, Silty Sand to Sandy Silt, Clayey Silt to Silty Clay (Glacial Till), Silty Clay, and Topsoil.&lt;/p&gt;
&lt;p&gt;Sand, silt, and clay describe the size of soil particles. Sand is the largest, clay is the smallest, and silt lies in between. Gravel soil has even larger particles than sand, containing many small stones.&lt;/p&gt;
&lt;p&gt;The price of sand and gravel has risen steadily over the last ten years, from $7.30 USD per metric ton in 2010 to $9.60 per metric ton in 2020. In the spirit of using 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-04-25-sensible-units/&#34;&gt;sensible units&lt;/a&gt;, let&amp;rsquo;s put this figure into something more tangible than dollars per metric ton for someone like myself who isn&amp;rsquo;t in construction.&lt;/p&gt;
&lt;p&gt;How about a single liter of soil? There are 625 liters in a metric ton of sand, so a single liter of soil is going to cost (at wholesale prices) 1.5 cents. You might say it&amp;rsquo;s&amp;hellip; dirt cheap. 🥁 (If you actually want to buy such a small volume of soil, you&amp;rsquo;ll probably end up buying 8 liters or so for $5, or 
&lt;a href=&#34;https://www.homedepot.com/p/40-lb-Top-Soil-71140180/100355705&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;40 lbs for $2.27&lt;/a&gt;, a significant markup on the 12 to 20 cents it costs at wholesale prices.)&lt;/p&gt;
&lt;p&gt;Dirt may be cheap, but it&amp;rsquo;s bought and sold in huge volume. The smallest soil volume supported on GetSoils is 100 m³. The largest is 200 times that. US consumption of sand and gravel in 2020 reached 68 million metric tons. That&amp;rsquo;s about 17 kilograms of soil consumed per person in the US per month. Did you consume 40 pounds of soil last month?&lt;/p&gt;
&lt;p&gt;The GetSoils website also allows you to list your bedrock:
Weathered Grey Shale (Georgian Bay Formation),
Competent Grey Shale (Georgian Bay Formation)
Weathered Red Shale (Queenston Formation),
Competent Red Shale (Queenston Formation), or
Other, as well as any previously placed manufactured materials: Recycled Granulars, Recycled Concrete, Recycled Asphalt, Other.&lt;/p&gt;
&lt;p&gt;Since bedrock can be listed both by buyers and sellers, I think this is for the purpose of buying and selling bedrock. However, it may also be there for logistics and reporting purposes; I&amp;rsquo;m not certain.
Weathered vs competent refers to the weathering on the bedrock, with weathered bedrock beginning to turn into soil, and competent bedrock remaining structurally intact.&lt;/p&gt;
&lt;p&gt;Georgian Bay Formation refers to a particular geoligical formation in Michigan, while Queenston Formation refers to one in Quebec.&lt;/p&gt;
&lt;p&gt;From this, I gather that Quebec and Michigan are target markets for the website. The website also lists the five boroughs of New York, so those must be target markets too.&lt;/p&gt;
&lt;p&gt;From the listing website, it looks like buying soil is intended for construction projects. Is it also appropriate for small volumes of soil, say for starting a vegetable garden or growing potted plants? The homepage suggests that it is, and the target market includes home owners, builders and developers, haulers and excavators, and other land owners.&lt;/p&gt;
&lt;p&gt;So &amp;ndash; back to marketing briefly to wrap up &amp;ndash; if you&amp;rsquo;re a home owner, builder, developer, hauler, excavator, or land owner, 
&lt;a href=&#34;https://getsoils.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;give GetSoils.com a try today!&lt;/a&gt; Help Dan Olshansky start the virtuous cycle of bootstrapping a new soil marketplace. (Help his company &lt;em&gt;take root&lt;/em&gt;. 😩) And finally, best of luck to Olshansky and the team in growing their new company! &lt;font size=&#34;2em&#34; color=&#34;lightgray&#34;&gt; (That they&amp;rsquo;ve recently &lt;em&gt;unearthed&lt;/em&gt;&amp;hellip; Okay, I&amp;rsquo;ll just click publish now. 👋)&lt;/font&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Sensible units -- Per capita isn&#39;t enough</title>
      <link>https://davidbieber.com/snippets/2021-04-25-sensible-units/</link>
      <pubDate>Sun, 25 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-04-25-sensible-units/</guid>
      
      <description>&lt;ul&gt;
&lt;li&gt;The world population is about 7.9 billion people.&lt;/li&gt;
&lt;li&gt;The global GDP is about 90 trillion USD.&lt;/li&gt;
&lt;li&gt;Global oil production is about 100 million barrels per day.&lt;/li&gt;
&lt;li&gt;The US federal budget for the 2020 fiscal year was set at $4.79 trillion USD.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this snippet we&amp;rsquo;ll take these statements, complete with their large and unwieldy numbers, and turn them into something a bit more tangible. A common (and very good strategy) for making large numbers tangible is to look at their per capita interpretation. Take the number, divide by the relevant population, and you start to get a better picture of what the number means. As we&amp;rsquo;ll see with our first example, this strategy isn&amp;rsquo;t always enough.&lt;/p&gt;
&lt;p&gt;How do we make the idea of 7.9 billion people more tangible?
Dividing by the world population here would be silly. The population is 1 person per capita. That&amp;rsquo;s not a useful statistic.&lt;/p&gt;
&lt;p&gt;Instead, we can use space and time to make it more tangible.&lt;/p&gt;
&lt;h2 id=&#34;population-per-unit-space&#34;&gt;Population per Unit Space&lt;/h2&gt;
&lt;p&gt;Here are some numbers we may find useful (too big to make immediate sense of for now, but we can deal with that momentarily):
The surface area of Earth is 196.9 million mi².
Of that, 57.51 million mi² is land area, and only about 24.64 million mi² of that is habitable.&lt;/p&gt;
&lt;p&gt;This gives us a global population density of 312 people per habitable square mile. Still not the most intuitive for two reasons: 1) a square mile is a pretty large area (Manhattan is 23 mi²; San Francisco is 47 mi²) and imagining 312 people scattered across it can be challenging, 2) the population density varies wildly across different regions (population density in Manhattan is 69,468 people per square mile; in San Francisco its 17,246 people per square mile).&lt;/p&gt;
&lt;p&gt;We can deal with reason (1) pretty simply. 312 people per habitable square mile is 89353 square feet per person. The Manhattan population density equals merely 401 square feet per person. The San Francisco population density equals 1616 square feet per person.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s tempting to compare these &amp;ldquo;square feet per person&amp;rdquo; figures to typical apartment sizes in these regions. &amp;ldquo;Four hundred square feet per person,&amp;rdquo; we might be tempted to remark, &amp;ldquo;no wonder apartments in the city are so small!&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Before we do that though, we have to remember two things: First, Manhattan&amp;rsquo;s 23 mi² isn&amp;rsquo;t all apartment space; it also includes public infrastructure like roads and parks, and commercial spaces like stores and offices. Only a fraction of the space is available for living.&lt;/p&gt;
&lt;p&gt;Second, redeemingly, Manhattan is built &lt;em&gt;up&lt;/em&gt; considerably. For every 10-story building built on 400 square feet of habitable land, we get nearly 4000 square feet of potential living space, not a mere 400.&lt;/p&gt;
&lt;p&gt;We can turn to 
&lt;a href=&#34;http://www.nyc.gov/html/housing/assets/downloads/pdf/housing_plan.pdf&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;New York&amp;rsquo;s 2014 ten-year housing plan&lt;/a&gt; to add more color to these numbers. There were 3.4 million units across New York City in 2014.&lt;/p&gt;
&lt;p&gt;A bit of Googling suggests the average apartment size in New York City is 700 square feet. Of course this is going to vary considerably by location and apartment type, and I don&amp;rsquo;t know how much we can trust this estimate. Still, let&amp;rsquo;s work with the number. Using the overall NYC population density of 27,000 people per square mile gives 1032 square feet per person. Meanwhile 3.4 million units × 700 ft²/unit at a population of 8.419 million people gives an apartment-population density of just 276 ft²/person. Dense!&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t know offhand all the factors I&amp;rsquo;m misrepresenting here. The 3.4 million figure is all housing units, not just apartments. However, the 700 square feet figure is (A) just for apartments, and (B) probably not an average across the whole city.&lt;/p&gt;
&lt;p&gt;Two main messages to take away from this analysis. (1) New York City is population dense and housing is scarce. (2) You can use space to give a clearer picture of population counts.&lt;/p&gt;
&lt;h2 id=&#34;population-per-unit-time&#34;&gt;Population per Unit Time&lt;/h2&gt;
&lt;p&gt;The global population growth rate is about 1.05% per year. That&amp;rsquo;s interesting, but what does it mean? How does that compare with 1.5% or 2%?&lt;/p&gt;
&lt;p&gt;Our approach to this statement will be to look at the effect of such a growth rate on a more modest size population.
In a city of 100,000 (like Mountain View, or New Haven), a growth rate of 1.05% means the population rises by 1050 people each year (about 1850 births and 700 deaths). That means about 5 babies are born in such a city each day!&lt;/p&gt;
&lt;p&gt;If the growth rate were double (2.1% instead of 1.05%, like it was at its peak in 1962), there would be 10 babies born in a 100,000 person city per day.&lt;/p&gt;
&lt;h2 id=&#34;global-gdp-and-the-us-federal-budget&#34;&gt;Global GDP and the US Federal Budget&lt;/h2&gt;
&lt;p&gt;The global GDP is $90 trillion USD. Dividing by the global population, we see the global GDP is $11,500 USD per capita.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a lot to unpack there that&amp;rsquo;s out of scope for this snippet. For now it suffices that this new figure is a lot more tangible than the original.&lt;/p&gt;
&lt;p&gt;Performing the same division for the US budget: $4.79 trillion / 328 million people gives a per capita budget of $14,600 USD. Again, there&amp;rsquo;s lots to unpack about this figure out of scope of the snippet, but it immediately makes thinking about budgets a little easier compared with the original figure. Now you can start asking questions like &amp;ldquo;how much should the government be spending on {social security, health care, defense} for &lt;em&gt;me&lt;/em&gt; individually, and for the average US citizen?&amp;rdquo; Collective budgeting is a weird problem, perhaps something to learn more about for a future snippet.&lt;/p&gt;
&lt;h2 id=&#34;oil-production&#34;&gt;Oil Production&lt;/h2&gt;
&lt;p&gt;One final example from my recent time spent learning about oil pricing. Global oil production is about 100 million barrels per day. US oil production is about 10 million barrels per day. How do we make sense of these numbers?&lt;/p&gt;
&lt;p&gt;Per capita figures aren&amp;rsquo;t enough.
I think the useful unit for these figures is &amp;ldquo;gallons per person per month&amp;rdquo;. This allows you to think about how much gas your car holds, and how often you have to fill it up. You can compare that with oil production in your country to get a rough sense of the scale of oil production.&lt;/p&gt;
&lt;p&gt;Globally oil production comes in at 1 barrel per person per 2.6 months. In the US, oil production comes in at 1 barrel per person per month. What&amp;rsquo;s your personal gas consumption rate? How does it compare with the US oil production rate? Are these rates useful to compare?&lt;/p&gt;
&lt;h2 id=&#34;recapping-the-original-statements&#34;&gt;Recapping the original statements&lt;/h2&gt;
&lt;p&gt;Here we take each of the original statements the way you might find it in a fact book,
and we restate them in more tangible terms.&lt;/p&gt;
&lt;p&gt;Original:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The world population is about 7.9 billion people.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Restated:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There are 90000 square feet of habitable land per person globally (1000 ft²/person in NYC, and 14000 ft²/person in a typical suburb.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Original:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The global population growth rate is about 1.05% per year.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Restated:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In a city of 100,000 (like Mountain View, or New Haven), the population rises by about 1050 people each year (1850 births, 700 deaths).&lt;/li&gt;
&lt;li&gt;That&amp;rsquo;s 5 new babies a day in this city on average!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Original:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The global GDP is about $90 trillion USD.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Restated:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The global GDP is $11,500 USD per capita.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Original:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Global oil production is about 100 million barrels per day.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Restated:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Global oil production comes is 1 barrel per person per 2.6 months.&lt;/li&gt;
&lt;li&gt;In the US, oil production is 1 barrel per person per month.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Original:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The US federal budget for the 2020 fiscal year was set at $4.79 trillion USD.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Restated:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The US federal budget per capita was $14,600 USD in 2020.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>What links here?</title>
      <link>https://davidbieber.com/snippets/2021-04-24-backlinks/</link>
      <pubDate>Sat, 24 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-04-24-backlinks/</guid>
      
      <description>&lt;p&gt;I wanted to write about backlinks today but didn&amp;rsquo;t get a chance (except you&amp;rsquo;re reading it, so of course I &lt;em&gt;did&lt;/em&gt; get a chance in the end).&lt;/p&gt;
&lt;p&gt;Quick outline of what I was hoping to write about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Backlinks appear in Roam Research&lt;/li&gt;
&lt;li&gt;I have a BrowserFlow flow that uses Google search to produce backlinks for any website&lt;/li&gt;
&lt;li&gt;And I saw that either some of Gwern&amp;rsquo;s writing or Less Wrong includes a &amp;ldquo;What links here?&amp;rdquo; section (it wasn&amp;rsquo;t clear to me which of Gwern or LessWrong was providing this functionality)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A backlink on a page X is an indication of what other content links to X. Seeing a list of backlinks can be mildly interesting, and I was curious to see what pages link to my own writing.&lt;/p&gt;
&lt;p&gt;I have some visibility into this through a couple different mechanisms. This website uses Google Analytics, so I can see where traffic comes from. This provides a decent view into what other websites are linking to my content. I can also see how traffic flows through my own site, which gives a limited view of the links between snippets.&lt;/p&gt;
&lt;p&gt;The second mechanism I can use to see what links to a snippet is Google Search&amp;rsquo;s exact match feature. Searching for a 
&lt;a href=&#34;https://www.google.com/search?q=%22https://davidbieber.com/snippets/%22&amp;#43;-site:https://davidbieber.com/snippets/&amp;amp;filter=0&amp;amp;biw=1648&amp;amp;bih=946&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;complete URL in quotes, optionally with &amp;ldquo;-site:urlgoeshereagain&amp;rdquo; in the query to remove links from the same domain,&lt;/a&gt; will show you what websites link to the page of interest. For example, the query 
&lt;a href=&#34;https://www.google.com/search?q=%22davidbieber.com/post/2019-12-29-track-your-life-in-a-spreadsheet/%22&amp;#43;-site:davidbieber.com&amp;amp;filter=0&amp;amp;biw=1648&amp;amp;bih=946&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&amp;ldquo;davidbieber.com/post/2019-12-29-track-your-life-in-a-spreadsheet/&amp;rdquo; -site:davidbieber.com&lt;/a&gt; shows links to 
&lt;a href=&#34;https://davidbieber.com/post/2019-12-29-track-your-life-in-a-spreadsheet/&#34;&gt;my Track Your Life in a Spreadsheet blog post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I was toying with the idea of adding some curated backlinks to snippets. Each snippet would show what other snippets reference it, as well as selected pages from around the web that reference it. Of course, there aren&amp;rsquo;t really pages around the web that reference my snippets, so this idea is moot at the moment.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Incomplete snippets</title>
      <link>https://davidbieber.com/snippets/2021-04-23-incomplete-snippets/</link>
      <pubDate>Fri, 23 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-04-23-incomplete-snippets/</guid>
      
      <description>&lt;p&gt;Yesterday and two days ago I started writing 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-04-22-sensible-units&#34;&gt;a snippet called &amp;ldquo;sensible units &amp;ndash; per capita isn&amp;rsquo;t enough&amp;rdquo;&lt;/a&gt;. In this snippet I take statements with big numbers and rewrite them to make them more intuitive. For example &amp;ldquo;The global population growth rate is about 1.05% per year.&amp;rdquo; becomes &amp;ldquo;In a city of 100,000 (like Mountain View, or New Haven), the population rises by about 1050 people each year (1850 births, 700 deaths). That&amp;rsquo;s 5 new babies a day in this city on average!&amp;rdquo;&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t finish the snippet though. While I hope to finish the snippet and publish it this weekend, this experience also made me think about how to publish incomplete snippets.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve had other incomplete snippets over the years. Peer Learning Group was initially an incomplete snippet back in July 2020, which I never published. Eventually (in January 2021) I decided to launch PLG without &amp;ldquo;finishing&amp;rdquo; the idea as I&amp;rsquo;d originally intended. The original idea was going to rely more heavily on automation and in principle could scale well. The actual idea I went with had a fair bit of manual coordination work, but was definitely worthwhile (in part because it actually happened!).&lt;/p&gt;
&lt;p&gt;My idea for publishing incomplete snippets is: to start, simply publish the snippet with a label &amp;ldquo;incomplete&amp;rdquo; in the title. Then, if I decide to continue the snippet, I will make a copy of the incomplete snippet, and change the date. If I finish it, I will remove incomplete from the title.&lt;/p&gt;
&lt;p&gt;Once I have a complete version of the snippet (which might sometimes never happen), I can link from the complete version to all the incomplete versions that preceded it. I may also remove the incomplete snippets from the main snippets index once a complete version is available. Or in that main index I may make the main link go to the complete version, with a smaller link that goes to the incomplete version.&lt;/p&gt;
&lt;p&gt;This idea requires a bit of development, but in the spirit of the idea itself, I think I&amp;rsquo;ll start publishing incomplete snippets even while the incomplete-snippet-publication-idea is itself incomplete.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Sensible units -- Per capita isn&#39;t enough (incomplete)</title>
      <link>https://davidbieber.com/snippets/2021-04-22-sensible-units/</link>
      <pubDate>Thu, 22 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-04-22-sensible-units/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;This is an 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-04-23-incomplete-snippets/&#34;&gt;&lt;strong&gt;incomplete&lt;/strong&gt; snippet&lt;/a&gt;. If I complete it, I&amp;rsquo;ll add a link to the completed snippet here. Update: 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-04-25-sensible-units&#34;&gt;Here&amp;rsquo;s the finished version.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The world population is about 7.9 billion people.&lt;/li&gt;
&lt;li&gt;The global GDP is about 90 trillion USD.&lt;/li&gt;
&lt;li&gt;Global oil production is about 100 million barrels per day.&lt;/li&gt;
&lt;li&gt;The US federal budget for the 2020 fiscal year was set at $4.79 trillion USD.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this snippet we&amp;rsquo;ll take these statements, complete with their large and unwieldy numbers, and turn them into something a bit more tangible. A common (and very good strategy) for making large numbers tangible is to look at their per capita interpretation. Take the number, divide by the relevant population, and you start to get a better picture of what the number means. As we&amp;rsquo;ll see with our first example, this strategy isn&amp;rsquo;t always enough.&lt;/p&gt;
&lt;p&gt;How do we make 7.7 billion people more tangible?
Dividing by the world population here would be silly. The population is 1 person per capita. That&amp;rsquo;s not a useful statistic.&lt;/p&gt;
&lt;p&gt;Instead, we can use space and time to make it more tangible.&lt;/p&gt;
&lt;h2 id=&#34;population-in-space&#34;&gt;Population in Space&lt;/h2&gt;
&lt;p&gt;Here are some numbers we may find useful (too big to make immediate sense of for now, but we can deal with that momentarily):
The surface area of Earth is 196.9 million mi².
Of that, 57.51 million mi² is land area, and only about 24.64 million mi² of that is habitable.&lt;/p&gt;
&lt;p&gt;This gives us a global population density of 312 people per habitable square mile. Still not the most intuitive for two reasons: 1) a square mile is a pretty large area (Manhattan is 23 mi²; San Francisco is 47 mi²) and imagining 312 people scattered across it can be challenging, 2) the population density varies wildly across different regions (population density in Manhattan is 69,468 people per square mile; in San Francisco its 17,246 people per square mile).&lt;/p&gt;
&lt;p&gt;We can deal with reason (1) pretty simply. 312 people per habitable square mile is 89353 square feet per person. The Manhattan population density equals 401 square feet per person. The San Francisco population density equals 1616 square feet per person.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s tempting to compare these &amp;ldquo;square feet per person&amp;rdquo; figures to typical apartment sizes in these regions. &amp;ldquo;Four hundred square feet per person,&amp;rdquo; we might be tempted to remark, &amp;ldquo;no wonder apartments in the city are so small!&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Before we do that though, we have to remember two things: First, Manhattan&amp;rsquo;s 23 mi² isn&amp;rsquo;t all apartment space; it also includes public infrastructure like roads and parks, and commercial spaces like stores and offices. Only a fraction of the space is available for living. Second, redeemingly, Manhattan is built &lt;em&gt;up&lt;/em&gt; considerably. For every 10-story building built on 400 square feet of habitable land, we get nearly 4000 square feet of potential living space, not a mere 400.&lt;/p&gt;
&lt;p&gt;We can turn to 
&lt;a href=&#34;http://www.nyc.gov/html/housing/assets/downloads/pdf/housing_plan.pdf&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;New York&amp;rsquo;s 2014 ten-year housing plan&lt;/a&gt; to add more color to these numbers. There were 3.4 million units across New York City in 2014.&lt;/p&gt;
&lt;p&gt;A bit of Googling suggests the average apartment size in New York City is 700 square feet. Of course this is going to vary considerably by location and apartment type, and I don&amp;rsquo;t know how much we can trust this estimate. Still, let&amp;rsquo;s work with the number. Using the overall NYC population density of 27,000 people per square mile (1032 square feet per person)&lt;/p&gt;
&lt;h2 id=&#34;population-in-time&#34;&gt;Population in Time&lt;/h2&gt;
&lt;p&gt;TODO&lt;/p&gt;
&lt;h2 id=&#34;recapping-the-original-statements&#34;&gt;Recapping the original statements&lt;/h2&gt;
&lt;p&gt;Here we take each of the original statements the way you might find it in a fact book,
and we restate them in more tangible terms.&lt;/p&gt;
&lt;p&gt;Original:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The world population is about 7.7 billion people.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Restated:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There is X square feet of habitable land per person globally (Y in a typical city, Z in a typical suburb)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Original:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The global population growth rate is about 1.05% per year.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Restated:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In a city of 100,000 (like Mountain View, or New Haven), the population rises by about 1050 people each year (1850 births, 700 deaths).&lt;/li&gt;
&lt;li&gt;That&amp;rsquo;s 5 new babies a day in this city on average!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;todo&#34;&gt;TODO:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The global GDP is about 90 trillion USD.&lt;/li&gt;
&lt;li&gt;Global oil production is about 100 million barrels per day.&lt;/li&gt;
&lt;li&gt;The US federal budget for the 2020 fiscal year was set at $4.79 trillion USD.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Early to bed, so no snippet</title>
      <link>https://davidbieber.com/snippets/2021-04-20-sleep-no-snippet/</link>
      <pubDate>Tue, 20 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-04-20-sleep-no-snippet/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;m going to sleep. It&amp;rsquo;s a bit after 10:10. So, I won&amp;rsquo;t write a lengthy snippet. That&amp;rsquo;s all. Perhaps more in the morning.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Python set operations</title>
      <link>https://davidbieber.com/snippets/2021-04-19-python-set-operations/</link>
      <pubDate>Mon, 19 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-04-19-python-set-operations/</guid>
      
      <description>&lt;p&gt;If you Google &amp;ldquo;Python set intersection&amp;rdquo;, you get a number of results about the &lt;code&gt;set.intersection&lt;/code&gt; function. It isn&amp;rsquo;t until the fourth result that you reach a page mentioning Python&amp;rsquo;s convenient syntax for performing set operations. This was surprising to me, hence this snippet.&lt;/p&gt;
&lt;h2 id=&#34;background-collections-in-python&#34;&gt;Background: Collections in Python&lt;/h2&gt;
&lt;p&gt;Python has a few primitive collection types: tuples, lists, dictionaries (aka dicts), and sets. Use parenthesis to create a tuple &lt;code&gt;(1, 2, 3)&lt;/code&gt;, square brackets to create a list &lt;code&gt;[4, 5, 6]&lt;/code&gt;, and squirrelly brackets to create a dict or set: &lt;code&gt;{7: 8, 9: 10}&lt;/code&gt; makes a dict and &lt;code&gt;{11, 12, 13}&lt;/code&gt; makes a set. Just like a set in mathematics, a set in Python is an &lt;strong&gt;unordered&lt;/strong&gt; collection of &lt;strong&gt;distinct&lt;/strong&gt; elements.&lt;/p&gt;
&lt;h2 id=&#34;convenient-syntax&#34;&gt;Convenient Syntax&lt;/h2&gt;
&lt;p&gt;Once you&amp;rsquo;ve constructed a set, the following operations allow you to perform set operations on it with clean concise syntax.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-md&#34;&gt;| for union.
&amp;amp; for intersection.
– for difference
^ for symmetric difference
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;operation-examples&#34;&gt;Operation Examples&lt;/h2&gt;
&lt;p&gt;Here are some examples:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;# Example 1: Disjoint sets (sets that have no elements in common)
{1, 2, 3} | {4, 5, 6} == {1, 2, 3, 4, 5, 6}
{1, 2, 3} &amp;amp; {4, 5, 6} == set()
{1, 2, 3} - {4, 5, 6} == {1, 2, 3}
{1, 2, 3} ^ {4, 5, 6} == {1, 2, 3, 4, 5, 6}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice how we cannot write &lt;code&gt;{}&lt;/code&gt; to create an empty set. That would create an empty dict. Instead we write &lt;code&gt;set()&lt;/code&gt;. (You can also write &lt;code&gt;tuple()&lt;/code&gt;, &lt;code&gt;list()&lt;/code&gt;, and &lt;code&gt;dict()&lt;/code&gt; to create empty tuples, lists, or dicts.)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;# Example 2: Overlapping sets
{&#39;red&#39;, &#39;green&#39;, &#39;blue&#39;} | {&#39;blue&#39;, &#39;yellow&#39;} == {&#39;red&#39;, &#39;green&#39;, &#39;blue&#39;, &#39;yellow&#39;}
{&#39;red&#39;, &#39;green&#39;, &#39;blue&#39;} &amp;amp; {&#39;blue&#39;, &#39;yellow&#39;} == {&#39;blue&#39;}
{&#39;red&#39;, &#39;green&#39;, &#39;blue&#39;} - {&#39;blue&#39;, &#39;yellow&#39;} == {&#39;red&#39;, &#39;green&#39;}
{&#39;red&#39;, &#39;green&#39;, &#39;blue&#39;} ^ {&#39;blue&#39;, &#39;yellow&#39;} == {&#39;red&#39;, &#39;yellow&#39;, &#39;green&#39;}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;set-augment-operations&#34;&gt;Set augment operations&lt;/h2&gt;
&lt;p&gt;Each of the operations &lt;code&gt;|&lt;/code&gt;, &lt;code&gt;&amp;amp;&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, and &lt;code&gt;^&lt;/code&gt; has a corresponding &amp;ldquo;augment&amp;rdquo; operation: &lt;code&gt;|=&lt;/code&gt;, &lt;code&gt;&amp;amp;=&lt;/code&gt;, &lt;code&gt;-=&lt;/code&gt;, and &lt;code&gt;^=&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When you use an augment operation, the operation is applied and the result is assigned back to the variable on the left hand side of the operation.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example of how to use these operations:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;# Example 3: Set augment operations (|=, &amp;amp;=, -=, and ^=)
x = {1, 2, 3}
x |= {3, 4, 5}
print(x)  # {1, 2, 3, 4, 5}
x &amp;amp;= {4, 5, 6}
print(x)  # {4, 5}
x -= {5, 6, 7}
print(x)  # {4}
x ^= {6, 7, 8}
print(x)  # {4, 6, 7, 8}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;set-elements-must-be-hashable&#34;&gt;Set elements must be hashable&lt;/h2&gt;
&lt;p&gt;Remember, sets can contain any elements as long as they are hashable. So, a set can contain numbers, strings, and bools. A set can also contain tuples, but not lists or dicts or other sets. If you want a set to contain a dict or another set, you can use a &amp;ldquo;frozendict&amp;rdquo; or &amp;ldquo;frozenset&amp;rdquo;, which are immutable hashable versions of dicts and sets.&lt;/p&gt;
&lt;p&gt;To check if an object &lt;code&gt;x&lt;/code&gt; is hashable, you can run &lt;code&gt;hash(x)&lt;/code&gt;. This will return the hash of &lt;code&gt;x&lt;/code&gt; if &lt;code&gt;x&lt;/code&gt; can be hashed, and will raise a TypeError otherwise.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Virtual table tennis coaching</title>
      <link>https://davidbieber.com/snippets/2021-04-18-virtual-table-tennis-coaching/</link>
      <pubDate>Sun, 18 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-04-18-virtual-table-tennis-coaching/</guid>
      
      <description>&lt;p&gt;For the last few weeks I&amp;rsquo;ve been playing virtual reality table tennis quite a lot. It&amp;rsquo;s competitive; some highly ranked real-life table tennis players from around the world play this game. My ranking has been going up: my ELO recently reached 2000+, bringing me (at least temporarily) into the top 1500 ranked players online (out of upwards of 440,000 players total.)&lt;/p&gt;
&lt;p&gt;Naturally, I&amp;rsquo;d like to make my number go up. So I practice. I play ranked and unranked games against people around the world. I practice against AI opponents. I use the virtual  ball machine. And I watch YouTube videos on how to hit the strokes appropriately.&lt;/p&gt;
&lt;p&gt;One thing I haven&amp;rsquo;t done though is get a coach.&lt;/p&gt;
&lt;p&gt;A few people have started offering in game virtual reality table tennis coaching. I think this is incredible. The coach and player play at the table simultaneously. They can stand on the same side of the table or opposite each other. They can use a ball machine together or hit with one another. They can discuss table tennis and do exercises together all in game.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m interested in giving virtual lessons a try. I&amp;rsquo;m not sure how good I&amp;rsquo;d be at receiving coaching though, and this is something I&amp;rsquo;d like to improve at. What makes for a good coach/player relationship? Players need psychological safety. Coaches need to be observant and knowledgeable. Players need to want to improve and ask good questions. Players need to be receptive to the suggestions of the coach. Players need to trust that the coach is focusing on the important aspects of play, so they can focus on the drill at hand. Coaches need to establish this trust. Players have to put in the time to improve.&lt;/p&gt;
&lt;p&gt;The table tennis quest game is still under active development, and the features that make coaching possible are still young. As I understand it, there aren&amp;rsquo;t special coaching features &amp;ndash; there&amp;rsquo;s just the capability for two people to stand around a shared table, optionally with a ball machine.&lt;/p&gt;
&lt;p&gt;Suppose the game developers were to add features to improve the coaching experience. What features would be essential? (1) Record and replay hits from a game or practice (2) Track stats during practice (3) Coach multiple people simultaneously across multiple tables (4) Mix and match replays&lt;/p&gt;
&lt;h3 id=&#34;record-and-replay&#34;&gt;Record and Replay&lt;/h3&gt;
&lt;p&gt;There are two reasons to want to record and replay hits from a game or practice. One is to learn to defend against them. Say you play against an opponent with a powerful serve or forehand smash. By recording and replaying their attack you can practice defending against it.&lt;/p&gt;
&lt;p&gt;The second reason to record and replay is to mimic or correct a shot. Let&amp;rsquo;s say you tend to hit your backhand loops into the net. It would be useful to replay the hit as a &amp;ldquo;ghost&amp;rdquo; that you can overlay your real paddle against. In this way you can make subtle adjustments in order to improve this shot. Similarly, you can take the powerful serve or forehand smash from the previous example and learn to mimic it by replaying it repeatedly and following along the motions with your own paddle.&lt;/p&gt;
&lt;h3 id=&#34;track-stats-during-practice&#34;&gt;Track stats during practice&lt;/h3&gt;
&lt;p&gt;An essential tool for self improvement is numbers that go up: ELO ratings, win counts, balls returned, etc. Giving the ball machine the capability of tracking how many balls you return successfully (where &amp;ldquo;success&amp;rdquo; is something you can define, such as hitting a certain region of the table, perhaps with a certain minimum speed or spin) and how many you miss creates a new metric to improve. And once there&amp;rsquo;s a metric to improve, putting in the time to improve it becomes all the more satisfying.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d love if the game could track a metric like this over time. This feature would pair especially well with the next one, allowing a coach to coach multiple people simultaneously, because it would give the coach quick visibility into the progress of the players towards their goals.&lt;/p&gt;
&lt;h3 id=&#34;coaching-multiple-people-across-multiple-tables&#34;&gt;Coaching multiple people across multiple tables&lt;/h3&gt;
&lt;p&gt;Currently coaching is a one on one affair. This is virtual reality though, so the potential for tools for coaching go way beyond what&amp;rsquo;s possible in the real world. A simple place to start is allowing the coach to simultaneously coach multiple people. The coach would do this by having all their students at various tables. The coach could have a multi-table view, where they can monitor all tables at once. Then, through VR magic the coach can quickly teleport to any of the tables to provide individual instruction. The coach can speak with players one on one, or to the whole group simultaneously. Similarly, the coach can set the ball machine settings for individual players or for the whole group. And the coach can pair off players to hit together or play matches or do exercises as they deem appropriate.&lt;/p&gt;
&lt;p&gt;The ball replay feature is of course also essential in this setting. If the coach observes a particularly good shot on any of the tables, they can capture this and replay it for all the players. Everyone can practice returning this one shot, whether it&amp;rsquo;s a smash, loop, or lob, to improve their table tennis game together.&lt;/p&gt;
&lt;h3 id=&#34;mixing-and-matching-replays&#34;&gt;Mixing and matching replays&lt;/h3&gt;
&lt;p&gt;The record and replay feature is going to be essential to the future of practice. Replaying a single ball over and over is useful, but it doesn&amp;rsquo;t capture the dynamic nature of table tennis. So, one useful feature to pair with replaying a shot is the ability to add variance to the shot. In the original recording, the smash has X speed and Y spin and hits precisely position Z. In the replays, all these values can be perturbed slightly to practice variations on the theme. Also, being able to build sequences of replay shots, much in the way you can turn on multiple ball machine settings today, would be a welcome addition for practicing in game situations.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t know which of these the game developers have planned. And of those that they have planned (they seem to have &lt;strong&gt;everything&lt;/strong&gt; planned), I wonder which are planned first. Once I&amp;rsquo;ve had my first coaching session, I&amp;rsquo;m sure my feature requests will only grow. Looking forward to it all. 🏓&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Resuming snippet writing?</title>
      <link>https://davidbieber.com/snippets/2021-04-17-resuming-snippet-writing/</link>
      <pubDate>Sat, 17 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-04-17-resuming-snippet-writing/</guid>
      
      <description>&lt;p&gt;About two month ago I encountered a 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-02-21-snippets-dry-spell/&#34;&gt;snippets dry spell&lt;/a&gt;. At the time I didn&amp;rsquo;t foresee writing snippets at the same rate I had been leading up to that point. Sure enough, over the two months that followed I only wrote a handful of snippets. March saw two simultaneous Peer Learning Groups, and April lead into a period of intense virtual ping pong playing and lots of real-life hiking.&lt;/p&gt;
&lt;p&gt;We wrapped up the Peer Learning Groups, a largely asynchronous low-commitment activity, with a virtual synchronous meet-up and coworking session. During these I produced these two snippets about what I learned for my PLG sessions: one on 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-04-15-oil-pricing/&#34;&gt;Laser Eye Surgery&lt;/a&gt;, one on 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-04-15-oil-pricing/&#34;&gt;Oil Pricing&lt;/a&gt;. I think this could be the trigger that brings me back into the pattern of writing snippets again, though I&amp;rsquo;m not certain.&lt;/p&gt;
&lt;p&gt;Setting out to write snippets once more, I have a handful of half-baked ideas about what to write about: sleep, ping pong, virtual reality, hiking, the 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-02-21-snippets-dry-spell/&#34;&gt;list of ideas from February&lt;/a&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, yet more snippets about Browserflow and Roam Research, machine learning research, PLG and other online learning ideas, and pandemic coping are all on my list.&lt;/p&gt;
&lt;p&gt;When I sat down today to pen a snippet, I initially thought I would write about my ideas for using virtual reality table tennis for group coaching sessions. It felt funny though; I wasn&amp;rsquo;t sure why I was writing it. Was snippets a place to collect good ideas I may want to share with people in the future?&lt;/p&gt;
&lt;p&gt;This snippet is me taking a moment to reflect on why I write snippets, to reload my old reasoning back into memory, and to see if it still makes sense to me.&lt;/p&gt;
&lt;p&gt;I had a few early reasons. Learning to communicate was a big one early on. Avoiding the addicting nature of social media was part of why I chose to write here, rather than on another platform. Feeling like I was writing for no audience, and the freedoms and desires that I found came with that, was a bigger reason for continuing on this platform rather than another. All of these continue to ring true, though there is one key way in which my writing deviates from its stated purpose.&lt;/p&gt;
&lt;p&gt;When I set out to get better at communicating, one of my motivations was for communicating research. I&amp;rsquo;ve hardly written about my research at all! I don&amp;rsquo;t want to make a big change here; I like the type of topic I tend to select for snippets, and I like the expectation that I&amp;rsquo;ve set for myself that I can write about anything, with the bar set extremely low. That said, I will make a small mental adjustment, and add to my internal Potential Topics List writing about my published research.&lt;/p&gt;
&lt;p&gt;So, with this snippet, I hope and intend that I am resuming somewhat more frequent writing. This is a non-promise, 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-10-08-biking-in-the-morning/&#34;&gt;a mere &amp;ldquo;aspirational intent&amp;rdquo; like the one I made about biking back in October&lt;/a&gt;. That one worked out though; I continued biking regularly well into the cold season, so I&amp;rsquo;m optimistic that this one will pan out positively as well.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Crashing Facebook Japan, The “content sharing group”, 2021 goals, The “programmer’s apprentice”, Making decisions for 10,000 people, Roam Primitives: subscribe to changes, and Castles in the clouds (as a mental model for belief systems) &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Eleven: Table Tennis VR</title>
      <link>https://davidbieber.com/snippets/2021-04-16-table-tennis-vr/</link>
      <pubDate>Fri, 16 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-04-16-table-tennis-vr/</guid>
      
      <description>&lt;p&gt;Adriana and I recently acquired a VR headset (an Oculus Quest 2), and I bought the game &amp;ldquo;Eleven: Table Tennis VR&amp;rdquo;.
My mind is blown. It&amp;rsquo;s like having a ping pong table that fits in your hands. You can bring it anywhere; it travels well. And if you do, you not only have everything you need to play ping pong (a table, paddles, $\infty$ balls, etc.) you also have thousands of people of every possible skill level always ready and eager to play.&lt;/p&gt;
&lt;p&gt;When you enter the game, it&amp;rsquo;s like standing at a ping pong table. Toss the ball from one hand, hit it with the paddle in the other. Simple. The physics is realistic. Lag, when present, is handled pretty well. When you hit the ball into the net, you don&amp;rsquo;t have to reach over and pick it up. When you hit the ball out, you don&amp;rsquo;t need to walk over and pick it up. You have infinity balls, and can play against AI opponents with infinity patience. You can play against real people too.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m beyond excited by this game. Being able to play ping pong with anyone around the world from the comfort of my own home is a science fiction future turned reality I didn&amp;rsquo;t realize I was missing. If you have the game &amp;ndash; it works on all sorts of different VR systems with cross-system play handled just fine &amp;ndash; do let me know. I would love to say hi over a game of table tennis.&lt;/p&gt;
&lt;p&gt;I expect multiple future snippets will contain musings about directions the game could go in, and I very much looking forward to seeing the game develop. 🏓&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Learning about Oil Pricing</title>
      <link>https://davidbieber.com/snippets/2021-04-15-oil-pricing/</link>
      <pubDate>Thu, 15 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-04-15-oil-pricing/</guid>
      
      <description>&lt;p&gt;For the March 2021 Climate Change Peer Learning Group, I spent a couple of hours learning about Oil Pricing. This proved far too large a topic to cover in the allotted time, far more so than for any of the other topics I&amp;rsquo;ve studied in a PLG before. Here&amp;rsquo;s what I learned.&lt;/p&gt;
&lt;h2 id=&#34;learning-trajectory&#34;&gt;Learning Trajectory&lt;/h2&gt;
&lt;p&gt;I started with Wikipedia and some assorted Googling to get the basics of crude oil, shale, natural gas, to get an idea for their rough production levels around the world, and to learn a bit of history about OPEC. Eventually, I landed on 
&lt;a href=&#34;https://www.e-education.psu.edu/eme801/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;this course from PennState: &lt;strong&gt;Energy Markets, Policy, and Regulation&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This course is an excellent resource, and I spent about an hour going through the first lesson (of 12), which is about the global market for crude oil. It was well written, interesting, and provided a good not-too-heavy mix of history, geopolitics, and economics to bring me up to speed.&lt;/p&gt;
&lt;p&gt;Future lessons promise to cover the markets for refined petroleum products, the markets for natural gas, and then further topics on natural gas, electricity, energy regulations, challenges with adopting renewables, and a number of related econ and finance topics.&lt;/p&gt;
&lt;p&gt;If you want a thorough introduction to the topic, check out 
&lt;a href=&#34;https://www.e-education.psu.edu/eme801/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;the course&lt;/a&gt;.
If you instead want a lighter more enjoyable exploration of the topic, check out 
&lt;a href=&#34;https://www.npr.org/sections/money/2016/08/26/491342091/planet-money-buys-oil&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Planet Money Buys Oil&lt;/a&gt;, a 20-minute episode of NPR&amp;rsquo;s &lt;em&gt;Planet Money&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&#34;understanding-oil&#34;&gt;Understanding Oil&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s crude oil, shale oil, and natural gas. Crude oil is found at a depth of about 6000 ft, and requires the most refining of the three to be useful. Shale oil is found at a depth of about 9000 ft. Natural gas is primarily methane, and requires the least work of the three to refine.&lt;/p&gt;
&lt;p&gt;Within each of these main categories of oil, there is a large numbers of kinds of oil. Take a look at the futures and indexes listed 
&lt;a href=&#34;https://oilprice.com/oil-price-charts/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;on these oil price charts&lt;/a&gt; to get a sense for how many different kinds of oil trade every day. The two at the top of the charts, West Texas Intermediate (WTI) and Brent, are the most important, as those two serve as benchmark oil prices for the rest.&lt;/p&gt;
&lt;p&gt;What makes an oil higher or lower quality? Two important dimensions are its sulfur content, and its viscosity. Oils low in sulfur are said to be &amp;ldquo;sweet&amp;rdquo;, while those high in sulfur are termed &amp;ldquo;sour&amp;rdquo;. The lower the sulfur content, the higher quality the oil. Viscosity of crude oil is measured on the API (&amp;ldquo;American Petroleum Institute&amp;rdquo;) gravity scale. Low viscosity oils are called &amp;ldquo;light&amp;rdquo;, and high viscosity oils are called &amp;ldquo;heavy&amp;rdquo;, with lower viscosity being preferable and more valuable than higher viscosity oils.&lt;/p&gt;
&lt;p&gt;WTI is a light sweet oil representative of the US market. Brent is a blend of light sweet crude oils from the North Sea, with just slightly higher levels of sulfur than WTI.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://firebasestorage.googleapis.com/v0/b/firescript-577a2.appspot.com/o/imgs%2Fapp%2Fplayground%2F-WMfNd5Pis.png?alt=media&amp;amp;token=f9149939-7126-438b-8487-4de6a601529c&#34; alt=&#34;Details about several different oil blends around the world.&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;oil-production-levels&#34;&gt;Oil Production Levels&lt;/h2&gt;
&lt;p&gt;US, Russian, and Saudi Arabia all producing near peak rates 9 to 11 million barrels per day.
In the US, that works out to about 1 barrel per person per month.
In the Russia, production is about 2 barrels per person per month.
And in Saudi Arabia, production is about 10 barrels per person per month.
(The differences here come from differences in the nations&#39; populations, not from their oil production levels, which are all the same order of magnitude.)&lt;/p&gt;
&lt;p&gt;I like thinking about production in terms of barrels per person per month because you get nice tangible values that you can compare to your own oil usage. How often do you get gas for your car? How long does it take you to go through a barrel of oil yourself? Far more than a month, I&amp;rsquo;m sure.&lt;/p&gt;
&lt;h2 id=&#34;a-wee-bit-of-history&#34;&gt;A Wee Bit of History&lt;/h2&gt;
&lt;p&gt;There were important oil embargos in 1973 and 1979. I&amp;rsquo;ll summarize what I read about briefly here, but I recommend reading through 
&lt;a href=&#34;https://www.e-education.psu.edu/eme801/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;the course&amp;rsquo;s text&lt;/a&gt; rather than this short summary.
In 1973: an unwarranted energy scare leads to the Arab oil embargo. The Middle East countries announce a 5% production cut per month as a reaction to the Yom Kippur war between Egypt and Israel. Though they announced a 5% decrease in production, in practice decreased production less than 1%.&lt;/p&gt;
&lt;p&gt;Main takeaway from this event: Cartel coordination is hard! Each country still had an individual profit motive, which prevented the embargo participants from carrying out their stated embargo.&lt;/p&gt;
&lt;p&gt;The 1979 embargo: An Iranian worker strike lead to oil prices rising. Again, this was mostly due to speculation not an actual production decrease.&lt;/p&gt;
&lt;p&gt;The main takeaways from these two events:  Fear of control due to OPEC is just as powerful (perhaps more so) as the actual control exerted by OPEC. More recently, fear of geopolitical instability in the Middle East and Africa has a similar effect. It&amp;rsquo;s abundantly clear there is so much important history and geopolitics that I haven&amp;rsquo;t gotten to read about yet.&lt;/p&gt;
&lt;h2 id=&#34;my-notes&#34;&gt;My Notes&lt;/h2&gt;
&lt;p&gt;There is lots more from the PennState course. I&amp;rsquo;ll recommend it one last time for anyone who wants to dive deeper into the subject. This is a massive topic and I spent a little under two hours reading about it. So, there&amp;rsquo;s much more to learn! To see what else I encountered in my brief foray into the topic, have a look at 
&lt;a href=&#34;https://roamresearch.com/#/app/commons-db/page/5AnRSW3BW&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;my notes here on Roam Research&lt;/a&gt;. They&amp;rsquo;re world-readable and world-editable, so feel free to peruse or even make contributions if you&amp;rsquo;re so inclined.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Learning about LASIK</title>
      <link>https://davidbieber.com/snippets/2021-04-08-laser-eye-surgery/</link>
      <pubDate>Thu, 08 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-04-08-laser-eye-surgery/</guid>
      
      <description>&lt;p&gt;My topic for the 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-03-11-peer-learning-group-topics/&#34;&gt;March 2021 Peer Learning Group&lt;/a&gt; was &amp;ldquo;Laser Eye Surgery.&amp;rdquo; So, I spent an hour learning about LASIK. Here&amp;rsquo;s what I learned.&lt;/p&gt;
&lt;h2 id=&#34;the-name-lasik&#34;&gt;The name &amp;ldquo;LASIK&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;LASIK stands for Laser-assisted in situ keratomileusis.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lasers&lt;/strong&gt;, which you&amp;rsquo;re probably familiar, emit high power beams of light. This is useful for laser eye surgery because a computer-guided laser can be used to precisely burn away pieces of your cornea in order to reshape your eye and correct your vision.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In situ&lt;/strong&gt; is Latin for &amp;ldquo;on site&amp;rdquo; or &amp;ldquo;in position&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Keratomileusis&lt;/strong&gt; comes from the Greek &lt;em&gt;κέρας&lt;/em&gt;/&lt;em&gt;kéras&lt;/em&gt; for &lt;em&gt;horn&lt;/em&gt; and &lt;em&gt;σμίλευσις&lt;/em&gt;/&lt;em&gt;smileusis&lt;/em&gt; for &lt;em&gt;carving&lt;/em&gt;, and refers to the reshaping of the cornea that is central to LASIK.&lt;/p&gt;
&lt;h2 id=&#34;how-does-lasik-work&#34;&gt;How does LASIK work?&lt;/h2&gt;
&lt;p&gt;Laser eye surgery uses a laser to reshape the cornea in your eye. By reshaping the cornea, it changes how your eye refracts light. And if done correctly (as it usually is!), this improves your vision.&lt;/p&gt;
&lt;p&gt;To access the cornea, the eye surgeon first cuts a flap into the surface of the cornea. This allows the surgeon to move that part of the cornea out of the way, exposing the remainder of the cornea. Once the flap is lifted, the surgeon uses a laser to reshape the cornea. Finally, the flap is returned to its original position and allowed to heal naturally.&lt;/p&gt;
&lt;p&gt;So, we summarize the process of LASIK with three steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Cut a flap into the cornea&lt;/li&gt;
&lt;li&gt;Reshape the cornea&lt;/li&gt;
&lt;li&gt;Reposition the flap to heal&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let&amp;rsquo;s go through the steps one by one.&lt;/p&gt;
&lt;h2 id=&#34;1-cutting-a-flap-into-the-cornea&#34;&gt;1. Cutting a flap into the cornea&lt;/h2&gt;
&lt;p&gt;There are two main approaches used for cutting this initial flap into the cornea: using a microkeratome or a femtosecond laser.&lt;/p&gt;
&lt;p&gt;A microkeratome is not a laser: it&amp;rsquo;s a mechanical device, basically a knife. That&amp;rsquo;s right, with the microkeratome approach the surgeon is more-or-less taking a knife to your eye.
It&amp;rsquo;s a special knife though, designed to create the micron-thin slip in the cornea needed to prepare your eye for LASIK.&lt;/p&gt;
&lt;p&gt;The second approach is the femtosecond laser, so called because its pulses last a few femtoseconds. That&amp;rsquo;s less than a picosecond! ($1\text{ fs} = 10^{-15}\text{ s}$)&lt;/p&gt;
&lt;p&gt;The flap we&amp;rsquo;re making here is really thin, measuring just 83 to 200 micrometers.&lt;/p&gt;
&lt;p&gt;
&lt;a href=&#34;https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4089871/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;This paper&lt;/a&gt; discusses common considerations in management and complications of the flap-cutting step in femtosecond laser LASIK.&lt;/p&gt;
&lt;p&gt;What are the possible complications? The paper lists &amp;ldquo;incomplete or partial flaps, free flaps, buttonholes, and small irregular flaps&amp;rdquo; as possible complications when using a microkeratome. The paper also describes the complications as &amp;ldquo;plaguing refractive surgeons&amp;rdquo; rather than plaguing the patients, which I think may be misdirected.&lt;/p&gt;
&lt;p&gt;My understanding is that femtosecond laser LASIK was steadily on the rise in 2008, and perhaps at this point is the standard approach to LASIK.&lt;/p&gt;
&lt;p&gt;The paper linked above lists these advantages of femtosecond LASIK over microkeratome LASIK: flap thickness reproducibility, wavefront measurements, stromal bed quality, and biomechanical outcomes.&lt;/p&gt;
&lt;p&gt;Regardless of what approach to cutting the flap the surgeon uses, this step takes just a couple of seconds. In fact, the whole procedure is rather short, lasting no more than a few minutes.&lt;/p&gt;
&lt;h2 id=&#34;2-reshaping-the-cornea&#34;&gt;2. Reshaping the cornea&lt;/h2&gt;
&lt;p&gt;This is the central step of LASIK! This is the step that can actually improve your vision. A computer-guided excimer laser removes part of the cornea, reshaping.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s a &amp;ldquo;computer-guided excimer laser&amp;rdquo;? It&amp;rsquo;s a powerful and precise laser capable of removing as little as 0.25 microns of tissue at a time. The &amp;ldquo;computer-guided&amp;rdquo; part of the laser uses eye-tracking to adjust where it cuts in response to any eye-movements you make.&lt;/p&gt;
&lt;p&gt;One of the perks of using a computer-guided laser is that it can respond quickly to any eye or head movements you make. If you move a little, it adjusts where it cuts. If you move too much, it shuts off the laser.&lt;/p&gt;
&lt;p&gt;Wikipedia informs me that the term &amp;ldquo;excimer&amp;rdquo; in excimer laser is a bit of a misnomer, and that &amp;ldquo;exciplex&amp;rdquo; would be more correct. An exciplex is an &lt;em&gt;excited complex&lt;/em&gt;, in our case an excited noble gas halide.&lt;/p&gt;
&lt;p&gt;During this step of LASIK, the excimer laser adjusts the shape of the cornea in order to correct the patient&amp;rsquo;s vision. Reshaping the cornea is an effective technique for correcting nearsightedness, farsightedness, and astigmatism.&lt;/p&gt;
&lt;p&gt;Nearsightedness occurs when the shape of your eye causes light to refract incorrectly such that images are focused in front of your retina, rather than directly &lt;em&gt;on&lt;/em&gt; your retina. Similarly, farsightedness occurs when your the shape of your eye causes the image to focus behind your retina. Vision impairments like these are perfect candidates for fixing with LASIK, since they can be remedied simply by modifying the shape of your cornea.&lt;/p&gt;
&lt;p&gt;To correct nearsightedness, the excimer laser is used to flatten the cornea. This causes incoming light to refract less, such that the focal point is moved further back, toward your retina. For farsightedness, the laser makes the cornea steeper, bringing the focal point forward in your eye. For an astigmatism, it aims to smooth the cornea into a more symmetrical shape.&lt;/p&gt;
&lt;h2 id=&#34;3-repositioning-the-flap-to-heal&#34;&gt;3. Repositioning the flap to heal&lt;/h2&gt;
&lt;p&gt;Once the cornea has been reshaped, the surgeon repositions the flap over the cornea. This acts as a natural bandage, and the cornea heals quickly.&lt;/p&gt;
&lt;h2 id=&#34;is-anesthesia-used&#34;&gt;Is anesthesia used?&lt;/h2&gt;
&lt;p&gt;Yes, eye numbing drops are given. You&amp;rsquo;re awake the whole time though. If you move a little, the computer-guidance will account for it. If you move too much, the laser will shut off automatically.&lt;/p&gt;
&lt;h2 id=&#34;risks&#34;&gt;Risks&lt;/h2&gt;
&lt;p&gt;Loss of vision is very rare. Dry eyes is common. Temporary vision problems like glare are common too.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the complete list of risks I found:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dry eyes&lt;/li&gt;
&lt;li&gt;Glare, halos, double vision&lt;/li&gt;
&lt;li&gt;Undercorrections&lt;/li&gt;
&lt;li&gt;Overcorrections&lt;/li&gt;
&lt;li&gt;Astigmatism&lt;/li&gt;
&lt;li&gt;Flap problems&lt;/li&gt;
&lt;li&gt;Regression&lt;/li&gt;
&lt;li&gt;Vision loss or changes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For myself, I would (naively) be primarily worried about regression. That said, it does seem to be an uncommon issue.&lt;/p&gt;
&lt;h2 id=&#34;costs&#34;&gt;Costs&lt;/h2&gt;
&lt;p&gt;LASIK is not usually covered by insurance, as it is typically considered elective surgery. The cost of LASIK is reported to be between $\text{\$1,000}$ and $\text{\$3,000}$ per eye. 
&lt;a href=&#34;https://www.vsp.com/eyewear-wellness/lasik-glasses-lenses/lasik-eye-surgery-cost&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;VSP has this page&lt;/a&gt; with a list of questions you should ask to understand exactly what is included in the cost of LASIK (Pre- and post- operative care? Follow-up procedures if fine-tuning is needed? One eye or two?).&lt;/p&gt;
&lt;h2 id=&#34;open-questions&#34;&gt;Open questions:&lt;/h2&gt;
&lt;p&gt;Keep in mind I only spent about an hour researching LASIK. There are many questions I am not qualified to answer. Here are some of the questions I still have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How common are each of the risks?&lt;/li&gt;
&lt;li&gt;How is the flap moved out of the way? How is it repositioned?&lt;/li&gt;
&lt;li&gt;What do the medical devices and surgery actually look like?&lt;/li&gt;
&lt;li&gt;For myself, I would be concerned that my vision changes too quickly. Is there a way to measure this to verify or invalidate this concern?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;peer-learning-group&#34;&gt;Peer Learning Group&lt;/h2&gt;
&lt;p&gt;I wrote up this topic at the conclusion to the March 2021 Peer Learning Group. We&amp;rsquo;re in between Peer Learning Groups right now. If you&amp;rsquo;re interested in participating in the next one, you can email me at &lt;a href=&#34;mailto:david810@gmail.com&#34;&gt;david810@gmail.com&lt;/a&gt; to be notified when sign-ups for the next Peer Learning Group session open up.&lt;/p&gt;
&lt;p&gt;During the PLG, I took my notes on Laser Eye Surgery 
&lt;a href=&#34;https://roamresearch.com/#/app/commons-db/page/vgNgwbZlz&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;in Roam Research here&lt;/a&gt;. The notes are publicly visible (and editable), so feel free to have a look. You can also see an image preview of them below.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://roamresearch.com/#/app/commons-db/page/vgNgwbZlz&#34;&gt;&lt;img align=&#34;center&#34; src=&#34;https://davidbieber.com/snippets/2021-04-08-lasiknotes.png&#34; alt=&#34;My Roam Research notes on Laser Eye Surgery.&#34; height=&#34;400px&#34;&gt;&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>March 2021 Peer Learning Group Topics</title>
      <link>https://davidbieber.com/snippets/2021-03-11-peer-learning-group-topics/</link>
      <pubDate>Thu, 11 Mar 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-03-11-peer-learning-group-topics/</guid>
      
      <description>&lt;p&gt;We have two simultaneous Peer Learning Groups running this month, one on all manner of miscellaneous topics, and one specifically on climate change. Here are the topics we&amp;rsquo;re learning about in each.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Misc topics:&lt;/strong&gt;&lt;br&gt;
March 2: Laser eye surgery&lt;br&gt;
March 12: Open-endedness in AI, evolution, and generative art&lt;br&gt;
March 15: The Alexander technique&lt;br&gt;
March 18: Game theory&lt;br&gt;
March 21: A taxonomy of humor&lt;br&gt;
March 22: Perspectives on finance and law&lt;br&gt;
March 24: Postmodernism through Lyotard&lt;br&gt;
March 27: Aging Biology&lt;br&gt;
March 28: Nutrition science&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Climate change topics:&lt;/strong&gt;&lt;br&gt;
March 3: Oil pricing&lt;br&gt;
March 8: Forecasts uncertainties (and expected values)&lt;br&gt;
March 13: Physics of climate change&lt;br&gt;
March 13: Greenhouse effect and atmospheric circulation&lt;br&gt;
March 17: Organizational climate change efforts&lt;br&gt;
March 22: Synthetic meat&lt;br&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Simplest Possible Case of the Efficient Minds Hypothesis Failing</title>
      <link>https://davidbieber.com/snippets/2021-03-10-efficient-minds-hypothesis-failing/</link>
      <pubDate>Wed, 10 Mar 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-03-10-efficient-minds-hypothesis-failing/</guid>
      
      <description>&lt;p&gt;Suppose you know $A$, and you know $A \to B$. Conventional wisdom suggests you also know $B$. However, this is not necessarily true. Conventional wisdom has incorrectly assumed the 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-03-04-the-efficient-minds-hypothesis/&#34;&gt;Efficient Minds Hypothesis&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Why isn&amp;rsquo;t this true? Isn&amp;rsquo;t it the first thing you&amp;rsquo;re taught in an Introductory Logic course? The reason is that it takes time and attention to conclude $B$ given that you know (1) $A$ and (2) $A \to B$. Whether or not you&amp;rsquo;ve noticed that you know both (1) and (2) and made the connection between them isn&amp;rsquo;t specified, so we can&amp;rsquo;t conclude that you&amp;rsquo;ve reached the conclusion $B$.&lt;/p&gt;
&lt;p&gt;You might object &amp;ldquo;well if &lt;em&gt;I&lt;/em&gt; knew $A$ and $A \to B$, I would conclude $B$ immediately. It&amp;rsquo;s obvious.&amp;rdquo; To this I would reply &amp;ldquo;not so fast &amp;ndash; no pun intended,&amp;rdquo; while clearly intending the pun.&lt;/p&gt;
&lt;p&gt;You might know thousands of facts $P_1, \cdots, P_{9000}$. Noticing that two of them collectively have the form (1) $A$ and (2) $A \to B$ is a bit like finding a needle in a haystack; there are $9000^2$ fact pairs in that set to consider. While finding the good pairs can sometimes be fast, it&amp;rsquo;s never immediate and sometimes doesn&amp;rsquo;t happen at all.&lt;/p&gt;
&lt;p&gt;Similarly, if you know (1) $A$ and (2) $B$, you still may not know $A\text{ and }B$. And if you know just (1) $A$, you may not realize $A\text{ or }B$. Each of these conclusions requires time and attention to reach, even if classical first order logic tells us the conclusions are trivial.&lt;/p&gt;
&lt;p&gt;That we are often able to perform inference really quickly is a remarkable thing, attributable to our brain&amp;rsquo;s natural but imperfect tendency to index information by its important properties. While our brains are remarkable, they are not perfectly efficient, and we should behoove ourselves not to fall prey to the fallacy of the Efficient Minds Hypothesis.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Healthy Games Inter-company Compact</title>
      <link>https://davidbieber.com/snippets/2021-03-08-healthy-games-inter-company-compact/</link>
      <pubDate>Mon, 08 Mar 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-03-08-healthy-games-inter-company-compact/</guid>
      
      <description>&lt;p&gt;This snippet is a silly, currently unworkable, but in my opinion still worthwhile idea to improve the healthiness of video games. Mobile games today are in an arms race. Make your game more addicting, and your game becomes more profitable. More addicting is not the same as more fun. They may be correlated, but the incentives of video game companies are not wholly aligned with the incentives of the players.&lt;/p&gt;
&lt;p&gt;Why is it an &amp;ldquo;arms race&amp;rdquo;? There&amp;rsquo;s limited mindshare. Making your game addicting claims more of this mindshare. More engaging games are more profitable. And there&amp;rsquo;s no easy way for a game company to disentangle unhealthy addictive engagement from increased engagement due to increased quality of the game (is this true? will ponder&amp;hellip;)&lt;/p&gt;
&lt;p&gt;Developers of these games will A/B test mechanisms and designs and select those that maximize engagement. This isn&amp;rsquo;t unique to video games; it applies to social media and advertising as well, but we&amp;rsquo;ll focus on video games for this snippet.&lt;/p&gt;
&lt;p&gt;Enter the &amp;ldquo;Healthy Games Inter-company Compact&amp;rdquo;. This is a hypothetical future agreement between all the video game companies. The &amp;ldquo;Healthy Games Inter-company Compact&amp;rdquo; (HGIC for short) states that once 100% of game companies agree to the compact, all video games will simultaneously reduce the addictiveness of their games by 20% (the specific number&amp;rsquo;s not central to the idea). Signing the agreement does nothing if not all video game companies have signed. Only once all such companies are signed the agreement does it come into effect. At that point, the agreement comes into effect for all companies at once, and all games are simultaneously made less addicting. (This idea is inspired by the real 
&lt;a href=&#34;https://en.wikipedia.org/wiki/National_Popular_Vote_Interstate_Compact&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Popular Vote Interstate Compact&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;There are so many reasons why this can&amp;rsquo;t work in practice. In the spirit of taking silly ideas seriously, let&amp;rsquo;s go through those reasons, and perhaps we&amp;rsquo;ll find some of them weaker than first appearance might suggest.&lt;/p&gt;
&lt;p&gt;The first reason it can&amp;rsquo;t work is that 100% of video game companies agreeing to &amp;ldquo;mutual disarmament&amp;rdquo; would be such an extraordinary feat. 
&lt;a href=&#34;https://en.wikipedia.org/wiki/Video_game_industry#Scope&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Wikipedia&lt;/a&gt; estimates that in the US alone there are 2,300 development companies and over 525 publishing companies. What would a consortium of all video game companies even look like? Why would 10% of companies agree to this compact, let alone 100%? A few could agree to it out of genuine interest in the health of their addiction-prone players. A few others could agree to it if it makes strategic sense for them. Getting to 10% seems farfetched, 100% fantastical.&lt;/p&gt;
&lt;p&gt;Second, even if all the current video game companies did agree, the market is such that a new player could enter the video game industry at any time, disregarding the compact. This HGIC would need to be legislation, not just an inter-company compact, for it to apply to new entrants. This is something I am doubtful I would support, even though the HGIC is my idea. It would proabably even take considerable effort to make a legislative version of the HGIC constitutional! (Is game mechanism design a protected form of speech?)&lt;/p&gt;
&lt;p&gt;Third, even if all current video game companies signed the HGIC, acted in good faith, and even if there were no possibility of new entrants, there still remain the difficult questions of how to measure the reduction in unhealthy addictiveness of games. As a strawman, the HGIC could specify a metric, say play-time per player, and all companies would reduce their play-time per player by an agreed upon percent. I&amp;rsquo;ll readily acknowledge this sounds ridiculous; it could mean ruining the fun of some games, not making them healthier! As a second strawman, the HGIC could specify specific game mechanics and how to adjust them. E.g. it would specify that count-down timers need to be shortened by X% (does that even help?), non-deterministic rewards need to be made Y% more deterministic, etc. I&amp;rsquo;ll readily acknowledge this strawman is ridiculous too; there are likely too many possible game mechanics for an agreement of this form to be manageable to produce. Finding an equivalent reduction in addictiveness across all games is impossible because games are simply too varied.&lt;/p&gt;
&lt;p&gt;Fourthly and finally, &lt;em&gt;everyone&lt;/em&gt; I&amp;rsquo;ve shared this idea with so far (three people in total) have disagreed with the premise, that the addicting nature of video games is a negative thing, and that reducing it is desirable. This is a real surprise to me. I thought it was generally accepted that the tactics employed by FarmVille, CandyCrush, Covet, and the like are deliberative exploitative and addictive, designed through experimentation to maximize engagement and profit, and that this is a negative aspect of the games. I suppose I was wrong about this (the generally accepted part, that is). Guess I need to expand my bubble.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;We now have four solid reasons that the Healthy Games Inter-company Compact could never come into effect. I&amp;rsquo;m sure there are a dozen more. It&amp;rsquo;s nevertheless nice to imagine a world in which a few companies draft and sign the compact, initially thinking it will never come into effect. And then, over time, more companies are drawn to the idea of improving the health of their addiction-prone customers, until eventually the industry enacts and broadly follows guidelines for healthy game development. I think that&amp;rsquo;s a world to aspire to, albeit unrealistic. So while the HGIC in all likelihood won&amp;rsquo;t work, perhaps there&amp;rsquo;s another path there.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;To get a glimpse of what people think outside my itsy-bitsy social bubble, you can have a look at 
&lt;a href=&#34;https://www.commonsensemedia.org/app-reviews/candy-crush-saga/user-reviews/adult&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;these mixed reviews of CandyCrush from parents and children&lt;/a&gt;. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>The Efficient Minds Hypothesis</title>
      <link>https://davidbieber.com/snippets/2021-03-04-the-efficient-minds-hypothesis/</link>
      <pubDate>Thu, 04 Mar 2021 13:36:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-03-04-the-efficient-minds-hypothesis/</guid>
      
      <description>&lt;p&gt;The &amp;ldquo;Efficient Minds Hypothesis&amp;rdquo; states that a person is able to reach whatever conclusions they are able to reach in a small finite amount of time. Unless new information is presented, after that small duration no new conclusions will be reached. Stated more succinctly, the Efficient Minds Hypothesis states that &amp;ldquo;thinking is near-instantaneous.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;This is of course, preposterous. However, when it is not named and stated so explicitly, believing the EMH is an easy trap to fall into.&lt;/p&gt;
&lt;p&gt;There are negative consequences to believing the EMH, even implicitly or subconsciously. It can lead to asking fewer questions. It can lead to scheduling less time for planning and Great Thoughts, and spending too large a proportion of your time on building and chasing short-term goals. It can lead to too much self-reliance, and a reluctance to delegate or share the burden of a project with others.&lt;/p&gt;
&lt;p&gt;While the Efficient Minds Hypothesis is mainly a strawman that I don&amp;rsquo;t think many people would claim to believe outright, I do think it&amp;rsquo;s an idea that people (at least myself) sometimes believe implicitly. Making it explicit helps to make its status as a fallacy clearer.&lt;/p&gt;
&lt;p&gt;I write about the Efficient Minds Hypothesis from personal experience. While I don&amp;rsquo;t consciously believe the EMH (as I stated above, I think it&amp;rsquo;s preposterous), I find that beneath the surface of my thoughts I often do believe it, and can act or think accordingly. Being surrounded by creative intelligent people at work, spending every day thinking about challenging problems, the falsity of the EMH (at least with respect to my own mind), has been crystal clear day after day.&lt;/p&gt;
&lt;p&gt;Its falsity is most clear when a colleague suggests a solution to a problem that I have that I have not seen. The solution feels like something simple enough to arrive at quickly given my experience, but it is apparently not, for it&amp;rsquo;s a solution I did not foresee. On N occasions it has even been the case that I have not even begun to properly start thinking about the problem when a colleague presents the solution, perhaps because there are many possible problems to attend to, and selecting where to place one&amp;rsquo;s attention is a problem in itself.&lt;/p&gt;
&lt;p&gt;Under the EMH, the idea that you can present a problem to a colleague without first having given it the small finite first attempt doesn&amp;rsquo;t make sense. If EMH were true, you would present only problems that you cannot yourself solve to your colleagues. In the time it takes to present a problem, you would have attempted solving it yourself.&lt;/p&gt;
&lt;p&gt;The maxims of &amp;ldquo;bring me solutions, not problems&amp;rdquo; and &amp;ldquo;don&amp;rsquo;t come to me until you&amp;rsquo;ve worked this out as much as you can on your own&amp;rdquo; are weakened by the lack of an EMH too. Sometimes you need to engage other minds simply to parallelize computation, not because one mind alone cannot solve something. The benefits of multiple minds go beyond parallelization though. Freshness and specialization are two principles that make a collaboration more than the sum of its parts.&lt;/p&gt;
&lt;p&gt;Why believe the EMH at all?&lt;/p&gt;
&lt;p&gt;When young, when working on easier problems, when you can anticipate what comes next, when your mind is fresh, well rested, and well equipped for the tasks at hand, the EMH can appear and feel true.
A quick look at any complex task, say chess or a hard math problem, makes it apparent that it&amp;rsquo;s not universally true. But those System 2 tasks do nothing to dispel the EMH in System 1 heavy situations.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;It isn&amp;rsquo;t always apparent that thinking takes time. It isn&amp;rsquo;t always apparent that System 1 thinking in particular takes time. It isn&amp;rsquo;t always apparent that something requires System 2 thought. And finally it isn&amp;rsquo;t always apparent that thinking has bandwidth, and that ideas and projects can be thought-bandwidth bottlenecked.&lt;/p&gt;
&lt;p&gt;The result is that we need to be deliberate with how we choose to spend our brainpower. And this starts with being mindful and intentional with our attention.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;As an exercise for the reader: Would the Efficient Minds Hypothesis imply the Efficient Market Hypothesis? How about the reverse?&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&amp;ldquo;System 1&amp;rdquo; and &amp;ldquo;System 2&amp;rdquo; refer to Kahneman&amp;rsquo;s dichotomy of fast intuitive (System 1) vs slow, deliberate, planned (System 2) thought from 
&lt;a href=&#34;https://en.wikipedia.org/wiki/Thinking,_Fast_and_Slow&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Thinking, Fast and Slow&lt;/a&gt;. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Brainstorming: Roam Terminal</title>
      <link>https://davidbieber.com/snippets/2021-02-24-brainstorming-roam-terminal/</link>
      <pubDate>Wed, 24 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-02-24-brainstorming-roam-terminal/</guid>
      
      <description>&lt;p&gt;In Roam Research, I&amp;rsquo;d like to be able to type &amp;ldquo;/terminal&amp;rdquo; to insert a shell into my current block. Each command issued in the shell will become a block hidden behind the terminal (nested but collapsed). The output of each command will become a block as well.&lt;/p&gt;
&lt;p&gt;What sorts of commands do you want to be able to issue from within Roam? Deploying snippets. Querying the Roam graph. sshing into another machine and using it natively. Treating Roam like a file system.&lt;/p&gt;
&lt;p&gt;Of course I&amp;rsquo;d like all the basic shell features (history, basic unix commands sed/grep/ls/cd/awk/&amp;hellip;, piping).&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d also like my commands to be able to use my Roam content as inputs. I&amp;rsquo;d like a new type of shell expansion &amp;ndash; expanding block references. echo $((7yNZl3Gf-)) will echo the contents of that block (precise syntax tbd).&lt;/p&gt;
&lt;p&gt;Pages in the Roam database can be treated like files. cat [[Roam Research]] will output the full contents of the Roam Research page of my graph.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll have new primitives too, like the unix classics, more suited for the Roam data structure. List all references on a page. grep that list for a keyword. Sort by date. &lt;code&gt;refs Roam Research | grep Conor | sort -t&lt;/code&gt;. There would be primitives for accessing a block&amp;rsquo;s children, parents, refs, backrefs, etc.&lt;/p&gt;
&lt;p&gt;Of course you can write your own commands too. Like 
&lt;a href=&#34;https://github.com/google/python-fire&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Python Fire&lt;/a&gt;, we&amp;rsquo;ll provide a mechanism to trivially translate any javascript/closure function in your roam/js into a command line utility. The function name becomes the command name. The function arguments become its flags. Help is generated automatically.&lt;/p&gt;
&lt;p&gt;The real power comes from being able to apply the unix philosophy simultaneously on Roam and on a remote machine. How does this look? Maybe the Roam graph is mounted as a filesystem on the remote machine. /roam/pages/Roam Research.md views [[Roam Research]] as a markdown file. Also viewable as json or edn. Syntactic sugar provided by the shell allows you to operate directly on &amp;ldquo;[[Roam Research]]&amp;rdquo; allowing for natural commands like the one above.&lt;/p&gt;
&lt;p&gt;You can write to pages and blocks via these unix utilities too. Makes it super easy to copy data between the remote machine and your graph in both directions.&lt;/p&gt;
&lt;p&gt;How to implement this? roam/render may be essential. 
&lt;a href=&#34;https://chrome.google.com/webstore/detail/secure-shell-app/pnhechapfaindjhompbnflcldabbghjo?hl=en&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Secure shell app&lt;/a&gt; (chrome extension) suggests feasibility. There&amp;rsquo;s a 
&lt;a href=&#34;https://en.wikipedia.org/wiki/Web-based_SSH&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;wikipedia page on Web-based SSH&lt;/a&gt; for inspiration. 
&lt;a href=&#34;https://xtermjs.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;xterm.js&lt;/a&gt; is used in loads of places for javascript-based terminals.&lt;/p&gt;
&lt;p&gt;Rerunning a command from your shell history? Appears as a block reference. Even works for modified commands.&lt;/p&gt;
&lt;p&gt;This just comes for free for being in Roam: you can tag your commands to make them easy to find later. In bash # starts a comment, so the syntax for tagging tag-teams nicely with bash&amp;rsquo;s syntax. Similarly using block and page references in your commands pages it easy to resurface them.&lt;/p&gt;
&lt;p&gt;For v0 we don&amp;rsquo;t necessarily need a roam/render UI. Instead we could just write some roam/js that listens for ENTER on blocks nested below &amp;ldquo;{{roam/terminal}}&amp;rdquo;. When ENTER is pressed, the block&amp;rsquo;s contents are parsed, the command gets run, output gets streamed to a new block nested below the command. I think a specialized UI could go a long way though. At the very least history search and tab completion are pretty essential shell features, and there are so many more (e.g. curses, colors).&lt;/p&gt;
&lt;p&gt;As I wrap up this idea, I&amp;rsquo;ll also point out the deep similarity between terminal UIs and chat UIs. Both are at their core just call and response. In one you communicate with the computer, in the other with human beings. (With 
&lt;a href=&#34;https://davidbieber.com/projects/bieber-bot&#34;&gt;Bieber Bot&lt;/a&gt; and my Messager project, it&amp;rsquo;s not always clear which is which 😃.) Details like the number of participants, the format of messages, and whether a response can be issued without a corresponding call are just that: details.&lt;/p&gt;
&lt;p&gt;If we could get a solid terminal experience, legitimately enabling developers to make Roam their default shell, the fusing of note-taking, thinking, and command-issuing that would result would be super powerful. All just a half-baked idea, for now. For now.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Snippets Dry Spell</title>
      <link>https://davidbieber.com/snippets/2021-02-21-snippets-dry-spell/</link>
      <pubDate>Sun, 21 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-02-21-snippets-dry-spell/</guid>
      
      <description>&lt;p&gt;After writing a snippet almost every day this year, the last week has been comparatively sparse. I&amp;rsquo;ve skipped about 7 days recently! Now, I don&amp;rsquo;t have any sort of quota that I&amp;rsquo;m aiming for (unlike last year, where I wanted to communicate publicly 100 times.) So, this isn&amp;rsquo;t necessarily a problem. Still, good to reflect on why I&amp;rsquo;ve slowed down in writing snippets and where I&amp;rsquo;ll go next.&lt;/p&gt;
&lt;p&gt;My recent snippets have been: quirky small Python projects&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, lots of Roam and Browserflow projects&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;, and some Peer Learning Group planning&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;. Essentially, almost all my writing has been project-based, usually about programming projects. It&amp;rsquo;s been a month since I&amp;rsquo;ve written about an idea I&amp;rsquo;m not actually acting on&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;. Let&amp;rsquo;s do more of those. I don&amp;rsquo;t want to set an expectation of myself that I write code or organize a big event for every little snippet. Snippets are supposed to be almost as easy for me to write and publish (but not to broadcast) as it is for me to think. So, self, expect some low-effort low-quality snippets in the coming weeks as we reset this expectation.&lt;/p&gt;
&lt;p&gt;This growing implicit expectation could be one reason for skipping several days lately. Another is the &amp;ldquo;OPP Back-pressure&amp;rdquo;. OPP stands for &amp;ldquo;Other People&amp;rsquo;s Projects.&amp;rdquo; I&amp;rsquo;ve found myself writing a lot about Roam Research, and a bit about Browserflow, both OPP. And with this &amp;ndash; particularly with writing about Roam &amp;ndash; comes an internal pressure to write less about OPP. Can explore this idea more later.&lt;/p&gt;
&lt;p&gt;Here are some of the snippet ideas I&amp;rsquo;ve written down for myself that I&amp;rsquo;d like to write eventually:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Crashing Facebook Japan&lt;/li&gt;
&lt;li&gt;The &amp;ldquo;content sharing group&amp;rdquo;&lt;/li&gt;
&lt;li&gt;2021 goals&lt;/li&gt;
&lt;li&gt;The &amp;ldquo;programmer&amp;rsquo;s apprentice&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Making decisions for 10,000 people&lt;/li&gt;
&lt;li&gt;Roam Primitives: subscribe to changes&lt;/li&gt;
&lt;li&gt;Castles in the clouds (as a mental model for belief systems)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As I get around to writing these, I can update this page with links to the snippets. (I don&amp;rsquo;t anticipate writing these in the short-term though.)&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;
&lt;a href=&#34;https://davidbieber.com/snippets/2021-01-18-python-hoist-locals-only/&#34;&gt;hoist&lt;/a&gt; and 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-02-17-python-magic-functions/&#34;&gt;magic&lt;/a&gt; and the 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-02-14-the-python-fire-shebang/&#34;&gt;Python Fire shebang&lt;/a&gt; and the 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-01-29-kangaroo-auto-responder/&#34;&gt;Kangaroo Auto-responder&lt;/a&gt;. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;
&lt;a href=&#34;https://davidbieber.com/tags/roam-research&#34;&gt;Here (Roam)&lt;/a&gt; and 
&lt;a href=&#34;https://davidbieber.com/tags/browserflow&#34;&gt;here (Browserflow)&lt;/a&gt; respectively. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;
&lt;a href=&#34;https://davidbieber.com/tags/peer-learning-group&#34;&gt;PLG snippets here.&lt;/a&gt; &lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;The latest examples are 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-01-22-am-i-available-for-conversation-right-now-dot-com/&#34;&gt;am i available for conversation right now dot com&lt;/a&gt; and my 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-01-20-clubhouse-feature-request-save-last-60-seconds/&#34;&gt;clubhouse feature request&lt;/a&gt;. &lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Magic Functions in Python</title>
      <link>https://davidbieber.com/snippets/2021-02-17-python-magic-functions/</link>
      <pubDate>Wed, 17 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-02-17-python-magic-functions/</guid>
      
      <description>&lt;p&gt;In this snippet I introduce and implement, but do not condone, Python &amp;ldquo;Magic functions&amp;rdquo;.
Magic functions are interesting to think about and to study, but I discourage their use in anything but the most experimental of code. You&amp;rsquo;ll soon see why.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;magic function&lt;/strong&gt; is a function where the arguments and return values are both implicit, handled through the magic of Python&amp;rsquo;s powerful stack introspection.&lt;/p&gt;
&lt;p&gt;Consider the following example, which implements the quadratic formula. Pay special attention to where quadratic_formula is called. No arguments are passed, and the result is not assigned to anything. Still, the program works.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import math
import magic

def quadratic_formula(context):
  magic.unpack(context)
  discriminant = b**2 - 4*a*c
  x0, x1 = (
      (-b + math.sqrt(discriminant)) / (2*a),
      (-b - math.sqrt(discriminant)) / (2*a),
  )
  return magic.context()


def main():
  a, b, c = 1, -1, -12
  magic.call(quadratic_formula)
  print(f&#39;x = {x0} or {x1}  (Discriminant is {discriminant})&#39;)

if __name__ == &#39;__main__&#39;:
  main()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We say quadratic_formula is a &amp;ldquo;magic function&amp;rdquo;, and it is called by invoking magic.call.&lt;/p&gt;
&lt;p&gt;When we run this program, the result is:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;x = 4.0 or -3.0  (Discriminant is 49)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How did a, b, and c get passed to quadratic_formula? How did x0, x1, and discriminant find their way back to main? This is the magic of magic functions.&lt;/p&gt;
&lt;p&gt;To implement a magic function, simply write a function that accepts a single argument &lt;code&gt;context&lt;/code&gt;, calls &lt;code&gt;magic.unpack(context)&lt;/code&gt; as its first line, and returns with &lt;code&gt;return magic.context()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To call a magic function, use &lt;code&gt;magic.call(fn)&lt;/code&gt; as in the example above.&lt;/p&gt;
&lt;p&gt;To &amp;ldquo;install&amp;rdquo; magic, so that you can import it as in the example above, simply save the following three-function Python file as &lt;code&gt;magic.py&lt;/code&gt; in the directory where you&amp;rsquo;d like to use magic functions.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import inspect

def call(fn, n=1):
  c = context(n=n+1)
  result = fn(c)
  unpack(result, n=n+1)

def context(n=1):
  c = {}
  caller = inspect.stack()[n]
  caller_frame = caller[0]
  caller_globals = caller_frame.f_globals
  caller_locals = caller_frame.f_locals
  c.update(caller_globals)
  c.update(caller_locals)
  return c

def unpack(c, n=1):
  caller = inspect.stack()[n]
  caller_frame = caller[0]
  caller_frame.f_globals.update(c)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These twenty lines of code comprise the complete implementation of the magic module.
Magic works by inspecting the stack to get the locals and globals when calling a magic function and when returning from a magic function &amp;ndash; this is done in the &lt;code&gt;context&lt;/code&gt; function. Magic then makes use of stack inspection a second time to update the globals in the caller after a magic function returns &amp;ndash; this is done in &lt;code&gt;unpack&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;What purpose does this all serve? Why would you ever want to use magic functions?
The short answer is that you should &lt;em&gt;never&lt;/em&gt; use magic functions.
They will confuse readers of your code and are error prone.
Nevertheless, I will explain the situation that prompted me to write this module.&lt;/p&gt;
&lt;p&gt;I wanted to write a machine learning training loop and reuse it for many different machine learning training pipelines. Each of the training pipelines needed to track metrics in its own way, save summaries in its own way, make plots in its own way, etc. A natural way to support all of these different needs is with hooks. A hook is a user provided callback function that the training loop library can call each iteration through the loop.&lt;/p&gt;
&lt;p&gt;The trouble with hooks in this situation is that they require either very long argument lists, or bundling of many arguments into a single argument. If different functions need different bundles of arguments, the bundling approach can be quite cumbersome. Also, if two hooks wish to communicate with one another, that needs to be accommodated too. Magic functions provide one mechanism for dealing with this complexity. Different magic hooks can make use of different parts of the training loop&amp;rsquo;s state. A magic hook can also use state set by another hook.
While this approach does satisfactorily address the complexity of writing a training loop library,
I must stress that I do not recommend this approach.&lt;/p&gt;
&lt;p&gt;As with real magic, use &lt;code&gt;magic&lt;/code&gt; at your own peril. 🧙‍♀️ 😉&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The Python Fire shebang</title>
      <link>https://davidbieber.com/snippets/2021-02-14-the-python-fire-shebang/</link>
      <pubDate>Sun, 14 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-02-14-the-python-fire-shebang/</guid>
      
      <description>&lt;p&gt;Happy valentine&amp;rsquo;s day! Today&amp;rsquo;s snippet is about a feature of 
&lt;a href=&#34;https://github.com/google/python-fire&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Python Fire&lt;/a&gt;, new in v0.4.0, and how you can use it to create Python Fire executables just by adding a shebang to an existing Python file. This idea is courtesy of 
&lt;a href=&#34;https://github.com/c6401&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;c6401&lt;/a&gt; in GitHub issue 
&lt;a href=&#34;https://github.com/google/python-fire/issues/319&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;#319&lt;/a&gt;. The shebang line is &lt;code&gt;#!/usr/bin/env -S python3 -m fire&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The feature introduced in fire v0.4.0 is that &lt;code&gt;python -m fire&lt;/code&gt; now accepts filepaths.&lt;/p&gt;
&lt;p&gt;Suppose you have a Python file at &lt;code&gt;path/to/module.py&lt;/code&gt;. Previously, you could invoke module.py as a Fire CLI with the command &lt;code&gt;python -m fire path.to.module&lt;/code&gt;. That still works, but now you can also use the command &lt;code&gt;python -m fire path/to/module.py&lt;/code&gt;. This is roughly equivalent to running module.py and then calling &lt;code&gt;fire.Fire()&lt;/code&gt; as the final line of the module.&lt;/p&gt;
&lt;p&gt;A consequence of this new feature is that the shebang &lt;code&gt;#!/usr/bin/env -S python3 -m fire&lt;/code&gt; allows you to create executable CLIs out of Python files. &lt;code&gt;/usr/bin/env -S&lt;/code&gt; is explained 
&lt;a href=&#34;https://www.gnu.org/software/coreutils/manual/html_node/env-invocation.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;here&lt;/a&gt;. To create a Python Fire executable, simply add the shebang line as the first line of the file, and then use &lt;code&gt;chmod +x&lt;/code&gt; to mark the file as executable.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a quick example:&lt;/p&gt;
&lt;script src=&#34;https://gist.github.com/dbieber/ab8ed63ebbd7afad3c1f19c70028ae31.js&#34;&gt;&lt;/script&gt;
&lt;p&gt;Save it as e.g. &lt;code&gt;shebang.py&lt;/code&gt;, run &lt;code&gt;chmod +x shebang.py&lt;/code&gt; to make it executable, and run it with &lt;code&gt;./shebang.py hello --name=David&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;&amp;gt; ./shebang.py hello --name=David
Hello David!
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Two more Browserflow flows for Roam Research</title>
      <link>https://davidbieber.com/snippets/2021-02-13-flows-for-roam-research/</link>
      <pubDate>Sat, 13 Feb 2021 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-02-13-flows-for-roam-research/</guid>
      
      <description>&lt;p&gt;I wrote three Browserflow flows for Roam Research today. None of them took me more than 20-30 minutes to write. The first one was for saving the current webpage to Roam. I 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-02-13-saving-urls-to-roam-with-browserflow/&#34;&gt;wrote about that flow here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The next flow I wrote is for saving any link you click on to Roam. The idea behind this flow is to prevent doing depth first exploration of the web. Better to look at a bunch of links and then later choose the most interesting, than to dive head first into the first link you click on.&lt;/p&gt;
&lt;p&gt;Video of that flow here:&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/KMxnws2Laww&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;And then I also wrote a flow for saving highlights from any web page to Roam. You can see that flow in action here:&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/MaV0GP4sZoM&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;In this flow, whenever I press enter the text I&amp;rsquo;ve highlighted is saved to my Roam Research Daily Notes page.&lt;/p&gt;
&lt;p&gt;Links to all the flows are in the video descriptions. Browserflow is currently in private beta. Looks like in the short-term DK will likely ask 
&lt;a href=&#34;https://www.notion.so/dkthehuman/Day-404-Choosing-My-Users-2a6b2c9cfc194fd3b561c370a62c60d5&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;$20&lt;/a&gt; for access to the private beta. You can join the waitlist at 
&lt;a href=&#34;https://browserflow.app&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;browserflow.app&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Saving URLs to Roam with Browserflow</title>
      <link>https://davidbieber.com/snippets/2021-02-13-saving-urls-to-roam-with-browserflow/</link>
      <pubDate>Sat, 13 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-02-13-saving-urls-to-roam-with-browserflow/</guid>
      
      <description>&lt;p&gt;Using the 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-02-12-javascript-functions-for-inserting-blocks-in-roam/&#34;&gt;Roam JavaScript primitives I wrote yesterday&lt;/a&gt; it was extremely easy (less than 10 minutes, I think) to create a robust Browserflow flow for saving URLs to Roam Research.&lt;/p&gt;
&lt;p&gt;Now when I&amp;rsquo;m browsing the web, I can press cmd-J (Browserflow&amp;rsquo;s keyboard shortcut) and choose &amp;ldquo;Roam: Save URL&amp;rdquo; from the typeahead to save the current URL to my Roam Daily Notes page.&lt;/p&gt;
&lt;p&gt;If there&amp;rsquo;s not already a &amp;ldquo;Saved URLs:&amp;rdquo; block on daily notes, it makes it. Then it nests the URL beneath.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what the flow looks like in action:&lt;/p&gt;
&lt;iframe width=&#34;640&#34; height=&#34;360&#34; src=&#34;https://www.youtube.com/embed/ORpBuE4UYSA&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;Here&amp;rsquo;s what the flow itself looks like:&lt;/p&gt;
&lt;img src=&#34;save-urls-flow.png&#34;/&gt;
&lt;p&gt;Notice there are really only two meaningful lines of code:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;let urls = await getOrCreateBlockOnPage($page, &#39;Saved URLs:&#39;, -1);
await createChildBlock(urls, $url)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first line creates the &amp;ldquo;Saved URLs:&amp;rdquo; block, but only if it doesn&amp;rsquo;t already exist. It returns the uid of that block. The second line saves the url. Nothing else to it!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>JavaScript Functions for Inserting Blocks in Roam</title>
      <link>https://davidbieber.com/snippets/2021-02-12-javascript-functions-for-inserting-blocks-in-roam/</link>
      <pubDate>Fri, 12 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-02-12-javascript-functions-for-inserting-blocks-in-roam/</guid>
      
      <description>&lt;p&gt;At the end of this snippet I include some helpful javascript functions for accessing and inserting pages and blocks in Roam Research. Hope you find these useful!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;getPage(page):&lt;/strong&gt; returns the uid of a specific page in your graph. &lt;em&gt;page&lt;/em&gt;: the title of the page.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;getOrCreatePage(page):&lt;/strong&gt; returns the uid of a specific page in your graph, creating it first if it does not already exist. &lt;em&gt;page&lt;/em&gt;: the title of the page.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;getBlockOnPage(page, block):&lt;/strong&gt; returns the uid of a specific block on a specific page. &lt;em&gt;page&lt;/em&gt;: the title of the page. &lt;em&gt;block&lt;/em&gt;: the text of the block.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;createBlockOnPage(page, block, order):&lt;/strong&gt; creates a new top-level block on a specific page, returning the new block&amp;rsquo;s uid. &lt;em&gt;page&lt;/em&gt;: the title of the page. &lt;em&gt;block&lt;/em&gt;: the text of the block. &lt;em&gt;order&lt;/em&gt;: (optional) controls where to create the block, 0 for top of page, -1 for bottom of page.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;getOrCreateBlockOnPage(page, block, order):&lt;/strong&gt; returns the uid of a specific block on a specific page, creating it first as a top-level block if it&amp;rsquo;s not already there. &lt;em&gt;page&lt;/em&gt;: the title of the page. &lt;em&gt;block&lt;/em&gt;: the text of the block. &lt;em&gt;order&lt;/em&gt;: (optional) controls where to create the block, 0 for top of page, -1 for bottom of page.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;getChildBlock(parent_uid, block):&lt;/strong&gt; returns the uid of a specific child block underneath a specific parent block. &lt;em&gt;parent_uid&lt;/em&gt;: the uid of the parent block. &lt;em&gt;block&lt;/em&gt;: the text of the child block.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;createChildBlock(parent_uid, block, order):&lt;/strong&gt; creates a new child block underneath a specific parent block, returning the new block&amp;rsquo;s uid. &lt;em&gt;parent_uid&lt;/em&gt;: the uid of the parent block. &lt;em&gt;block&lt;/em&gt;: the text of the new block. &lt;em&gt;order&lt;/em&gt;: (optional) controls where to create the block, 0 for inserting at the top, -1 for inserting at the bottom.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;getOrCreateChildBlock(parent_uid, block, order):&lt;/strong&gt; returns the uid of a specific child block underneath a specific parent block, creating it first if it&amp;rsquo;s not already there. &lt;em&gt;parent_uid&lt;/em&gt;: the uid of the parent block. &lt;em&gt;block&lt;/em&gt;: the text of the child block. &lt;em&gt;order&lt;/em&gt;: (optional) controls where to create the block, 0 for inserting at the top, -1 for inserting at the bottom.&lt;/p&gt;
&lt;p&gt;Caution ⚠️ If multiple blocks with the same text exist on the page, these functions may return the uid of the wrong block.&lt;/p&gt;
&lt;script src=&#34;https://gist.github.com/dbieber/795cf15cad6b46cfbd6cc8213900925d.js&#34;&gt;&lt;/script&gt;
&lt;p&gt;To use these functions in your Roam database, create a block with the string &lt;code&gt;{{[[roam/js]]}}&lt;/code&gt;, create a code block by typing triple-backticks (```), paste the above JavaScript into the code block, and click &amp;ldquo;Yes, I know what I&amp;rsquo;m doing.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;As a reminder, you get the result of an async function with &lt;code&gt;await&lt;/code&gt;, e.g.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;let uid = await getOrCreateBlockOnPage(
    &amp;quot;February 12, 2020&amp;quot;, &amp;quot;Fleeting TODOs:&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The create- and getOrCreate- functions are async, whereas the pure get- functions are regular functions. So, be sure to use await accordingly.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Find yourself typing cmd-t t ENTER often?</title>
      <link>https://davidbieber.com/snippets/2021-02-10-find-yourself-typing-t-enter-often/</link>
      <pubDate>Wed, 10 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-02-10-find-yourself-typing-t-enter-often/</guid>
      
      <description>&lt;p&gt;A common attention pitfall is to mindlessly type cmd-t t ENTER. cmd-t creates a new tab. &amp;ldquo;t&amp;rdquo; autocompletes to twitter.com. ENTER. Four keystrokes and you&amp;rsquo;re scrolling. &amp;ldquo;r&amp;rdquo; for reddit. &amp;ldquo;f&amp;rdquo; for facebook. etc.&lt;/p&gt;
&lt;p&gt;Less than a second of mindless activity, leading to hundreds of seconds (minutes? hours?) of scrolling that you didn&amp;rsquo;t intend to do.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the solution. &lt;strong&gt;Delete websites from your browser&amp;rsquo;s autocomplete.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s easy to do. On Mac, it&amp;rsquo;s &lt;strong&gt;fn-shift-delete&lt;/strong&gt;. On Windows, just shift-delete.&lt;/p&gt;
&lt;p&gt;Just select the website from Chrome&amp;rsquo;s dropdown and press fn-shift-delete, and the website is removed from your browser&amp;rsquo;s autocomplete.&lt;/p&gt;
&lt;p&gt;In Firefox, it&amp;rsquo;s even easier: just press shift-delete.&lt;/p&gt;
&lt;p&gt;Eventually the websites will make their way back into your autocomplete, but it will take a while for this to happen. And when it does, now you know what to do: fn-shift-delete.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What does Browserflow do beyond what Tampermonkey does?</title>
      <link>https://davidbieber.com/snippets/2021-02-09-what-does-browserflow-do-beyond-what-tampermonkey-does/</link>
      <pubDate>Tue, 09 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-02-09-what-does-browserflow-do-beyond-what-tampermonkey-does/</guid>
      
      <description>&lt;p&gt;Someone recently asked me what 
&lt;a href=&#34;https://dkthehuman.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;DK&lt;/a&gt;&amp;rsquo;s 
&lt;a href=&#34;http://browserflow.app/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Browserflow&lt;/a&gt; does beyond what e.g. 
&lt;a href=&#34;https://www.tampermonkey.net/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Tampermonkey&lt;/a&gt; provides. Here&amp;rsquo;s my answer.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;1. &lt;em&gt;&lt;strong&gt;Way&lt;/strong&gt;&lt;/em&gt; easier to use both for programmers and non-programmers&lt;/p&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;
&lt;p&gt;Allows recording macros or writing them as &amp;ldquo;flows&amp;rdquo;/programs&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Everything (okay, maybe not &lt;em&gt;everything&lt;/em&gt;) &amp;ldquo;just works&amp;rdquo; &amp;ndash; e.g. if you want to write a for loop over tweets on Twitter, you just do. No need to deal with handling scrolling, or with race conditions about when dom elements appear and disappear, or if twitter decides to reuse dom elements, etc. Browserflow takes care of those details.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Provides high level commands like taking screenshots of elements, writing to csv, selecting parts of a page, looping over elements, getting input from the user, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Easy to share flows with other users! Unfortunately there&amp;rsquo;s like ~2 other users right now 😛&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The typeahead for running flows is super convenient. cmd-J then type a piece of the flow name, then hit enter. The flow runs.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;Really it&amp;rsquo;s (3) that sets it apart. The attention to detail in the product is impressive. Thanks DK.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;My experience with Tampermonkey is limited, so take this with some salt. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Repurposing my Twitter Feed</title>
      <link>https://davidbieber.com/snippets/2021-02-08-repurposing-my-twitter-feed/</link>
      <pubDate>Mon, 08 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-02-08-repurposing-my-twitter-feed/</guid>
      
      <description>&lt;p&gt;Twitter&amp;rsquo;s addicting. It&amp;rsquo;s not a good use of my time, but I scroll there anyway. If I&amp;rsquo;m going to be scrolling there anyway, might as well make it worthwhile. So, I&amp;rsquo;ve decided to repurpose my Twitter timeline and inject things I actually care about into it.&lt;/p&gt;
&lt;p&gt;How? You might think to do this with a Chrome extension, injecting content in between the existing tweets. There&amp;rsquo;s an easier way though. I&amp;rsquo;ve made a new, private Twitter account, and I programmatically&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; tweet as that.&lt;/p&gt;
&lt;p&gt;My personal Twitter account is @Bieber, and I use a picture of myself for the profile. The new account goes by &amp;ldquo;Private Bieber&amp;rdquo;, and uses a deep dream-ified version of my profile picture.&lt;/p&gt;
&lt;p&gt;How does it decide what to tweet? It chooses tweets from my Roam Research database. I already frequently write down things I&amp;rsquo;d like to learn about, and ideas I&amp;rsquo;d like to try in Roam. It&amp;rsquo;s where I keep my snippet ideas, my spaced repetition system, and my &amp;ldquo;Fleeting TODOs&amp;rdquo;. Source code available in the footnotes.&lt;/p&gt;
&lt;p&gt;Fleeting TODOs are what I call TODO items that tug at my brain in the moment, eager to take my attention away from the task at hand. Rather than do them then, I write them down. I only ever get around to doing a small fraction of my fleeting TODOs, but it&amp;rsquo;s nice to have a record of them. It makes it easier to notice if I keep coming back to the same idea, in which case maybe it&amp;rsquo;s worth actually pursuing.&lt;/p&gt;
&lt;p&gt;So, I have a script that occasionally &amp;ndash; currently every 10 minutes &amp;ndash; picks out one of these items from my Roam Research database and tweets it in a way that&amp;rsquo;s only visible to me.&lt;/p&gt;
&lt;p&gt;Since I have my Twitter feed configured to show me tweets chronologically, this means there&amp;rsquo;s always a tweet from Private Bieber sitting at the top, to remind me of something &lt;em&gt;I&lt;/em&gt; care about, rather than something the &lt;em&gt;Twitter algorithm&lt;/em&gt; has picked out for me to care about.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://firebasestorage.googleapis.com/v0/b/firescript-577a2.appspot.com/o/imgs%2Fapp%2Fplayground%2FxD83QrK9_D.png?alt=media&amp;amp;token=76f275ac-62fd-4844-829c-b44cf9cf568f&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Currently the tweet selection is random, but already in this first 20 minutes I&amp;rsquo;ve been happy with the tweets it&amp;rsquo;s been writing. Perhaps in a future iteration I&amp;rsquo;ll make some adjustments to what it tweets and when. It&amp;rsquo;s nice to have this kind of control over my attention, especially in a setting like Twitter where I&amp;rsquo;m so used to mindless scrolling.&lt;/p&gt;
&lt;p&gt;This same technique ought to work fine for taking control of my Facebook feed too, so perhaps I&amp;rsquo;ll get Private Bieber an account there next.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;
&lt;a href=&#34;https://gist.github.com/dbieber/47660493954e62f4607cd8d19d54cf59&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Source code is here.&lt;/a&gt; &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Peer Learning Group Sign Up</title>
      <link>https://davidbieber.com/snippets/2021-02-07-peer-learning-group-sign-up/</link>
      <pubDate>Sun, 07 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-02-07-peer-learning-group-sign-up/</guid>
      
      <description>&lt;p&gt;Peer Learning Group is an experiment for learning new things and meeting new people. I&amp;rsquo;d love for you to join.
The experiment will last for four weeks, and requires only a small time commitment during this period (just a few hours total).
During these four weeks, you will learn about several topics, and you will also teach the group about one or two topics yourself.
The next peer learning group session will be March 1 - March 28, 2021.
If this interests you, I encourage you to sign up here.
Additional details about &amp;ldquo;how it works&amp;rdquo; below the fold. We&amp;rsquo;re 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-02-07-ways-to-improve-peer-learning-group/&#34;&gt;making some changes&lt;/a&gt; compared to the first group.&lt;/p&gt;
&lt;iframe src=&#34;https://docs.google.com/forms/d/e/1FAIpQLSfxG5T0ljW4DAKTM5M0nedNnkMmxxAPgywwv0VZcFAAlWR0yQ/viewform?embedded=true&#34; width=&#34;640&#34; height=&#34;920&#34; frameborder=&#34;0&#34; marginheight=&#34;0&#34; marginwidth=&#34;0&#34;&gt;Loading…&lt;/iframe&gt;
&lt;h2 id=&#34;how-it-works&#34;&gt;How it works&lt;/h2&gt;
&lt;p&gt;On March 1, everyone will be added to a Facebook Messenger group chat. I&amp;rsquo;m targeting a group of about 6-8 people.&lt;/p&gt;
&lt;p&gt;Behind the scenes, I will be contacting everyone to learn what they are interested in learning about. I&amp;rsquo;ll coordinate with you to figure out 1 or 2 topics for you to teach the group about. We&amp;rsquo;ll try to choose topics that both excite you &lt;strong&gt;and&lt;/strong&gt; that &lt;em&gt;someone else&lt;/em&gt; in the group is interested in. We&amp;rsquo;ll also select a day for you to do the learning and teaching.&lt;/p&gt;
&lt;p&gt;On the chosen day, you&amp;rsquo;ll be expected to spend about an hour learning about the selected topic, and sharing what you learn with the group chat. You&amp;rsquo;re welcome to learn about the topic in advance, but that&amp;rsquo;s absolutely not required!&lt;/p&gt;
&lt;p&gt;How you share what you&amp;rsquo;ve learned with the group is up to you, but the bar is low. There&amp;rsquo;s no expectation of putting together a lesson plan. Instead, I&amp;rsquo;m envisioning you &amp;ldquo;live tweeting&amp;rdquo; interesting things as you learn them, putting quotes, images, and explanations into the chat that you think communicate the main ideas clearly. But I&amp;rsquo;ll reiterate: how you share what you&amp;rsquo;ve learned is completely up to you, and we&amp;rsquo;re setting our expectations low.&lt;/p&gt;
&lt;p&gt;Everyone else is welcome to discuss, ask questions, share insights, etc. The chat is there for you to use how you please.&lt;/p&gt;
&lt;p&gt;Since an hour is a relatively short period of time, I&amp;rsquo;ll try to allocate topics to you that are at the fringes of your expertise already. My theory is that while an hour is fairly short, it will still be really rewarding to hear what someone else learns from a concentrated hour of study.&lt;/p&gt;
&lt;p&gt;At the end of the four week period, you&amp;rsquo;ll have &amp;ldquo;presented&amp;rdquo; once or twice, and collectively we&amp;rsquo;ll have learned about ~10 different topics in total.&lt;/p&gt;
&lt;p&gt;The goal is to meet people and learn new things, and also to have fun. So come curious and with an open mind, and we&amp;rsquo;ll do our best to make this an interesting and enjoyable month.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Ways to improve Peer Learning Group</title>
      <link>https://davidbieber.com/snippets/2021-02-07-ways-to-improve-peer-learning-group/</link>
      <pubDate>Sun, 07 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-02-07-ways-to-improve-peer-learning-group/</guid>
      
      <description>&lt;p&gt;In this snippet I list out things I plan to do to improve Peer Learning Group for a future iteration.&lt;/p&gt;
&lt;h3 id=&#34;1-fewer-topics-per-day&#34;&gt;1. Fewer topics per day&lt;/h3&gt;
&lt;p&gt;In the first round of Peer Learning Group, we had a topic almost every single day, with just two days off in the middle.&lt;/p&gt;
&lt;p&gt;In the next round, I&amp;rsquo;ll either have fewer people or a longer period of time for the program (e.g. 4-6 weeks), such that there&amp;rsquo;s only ever someone teaching every 3-5 days.&lt;/p&gt;
&lt;p&gt;This gives more time to think, reflect, and breathe. More time to have adhoc discussions without feeling like you&amp;rsquo;re talking out of turn. More time for questions and connections between topics to bubble up. More time for unrelated topics to come up.&lt;/p&gt;
&lt;h3 id=&#34;2-give-people-topics-theyre-interested-in&#34;&gt;2. Give people topics they&amp;rsquo;re interested in&lt;/h3&gt;
&lt;p&gt;In the first round of Peer Learning Group, I aimed to give people topics at the edge of their expertise. I tried to give people a topic that would really interest &lt;em&gt;someone else&lt;/em&gt; in the group. In the next iteration, I&amp;rsquo;ll try to pick topics for people that more closely align with their own interests. Still not things that they&amp;rsquo;re experts in already, but rather topics that they&amp;rsquo;re excited to learn about themselves. I&amp;rsquo;ll still aim to make sure the topics we choose are interesting to other people in the group too.&lt;/p&gt;
&lt;h3 id=&#34;3-choose-a-unifying-theme-for-the-group-maybe&#34;&gt;3. Choose a unifying theme for the group, maybe&lt;/h3&gt;
&lt;p&gt;In the first round, the topics were pretty diverse: we had &amp;ldquo;cultivating conscious leadership&amp;rdquo;, the Ethereum EVM, Jungian archetypes, Microbubbles, carcinisation, complexity management, and several more. There was minimal overlap in the ~40 topic suggestions I received while setting up the group.&lt;/p&gt;
&lt;p&gt;For the next round, I&amp;rsquo;m toying with the idea of picking an overarching topic, like climate change, machine learning, math, or physics.&lt;/p&gt;
&lt;p&gt;Curious to hear what people think of this idea.&lt;/p&gt;
&lt;h3 id=&#34;4-encourage-use-of-background-knowledge&#34;&gt;4. Encourage use of background knowledge&lt;/h3&gt;
&lt;p&gt;This is more about my own teaching experience than running the group overall. As I was teaching my topic (Asynchronous Teaching), I was initially reticent to share things I already knew, instead focusing on sharing only what I learned during my teaching session. In retrospect, it is definitely valuable to share background knowledge, not just newly obtained information.&lt;/p&gt;
&lt;p&gt;Curious to hear if other people had a similar experience to myself on this.&lt;/p&gt;
&lt;h3 id=&#34;5-include-a-synchronous-component&#34;&gt;5. Include a synchronous component&lt;/h3&gt;
&lt;p&gt;Pretty much everything was asynchronous in the first group. Not too late to change this though! Even though our Peer Learning Group experiment is coming to a close, we can still set up a synchronous social gathering for next week.&lt;/p&gt;
&lt;h3 id=&#34;6-ask-more-questions&#34;&gt;6. Ask more questions&lt;/h3&gt;
&lt;p&gt;This is a personal change I would make, not a group change. In the next round, I&amp;rsquo;m going to make more of an effort to ask well thought out questions on many of the topics.&lt;/p&gt;
&lt;h3 id=&#34;thank-you&#34;&gt;Thank you&lt;/h3&gt;
&lt;p&gt;I really enjoyed the first Peer Learning Group. Every evening there was a new thread about an interesting topic delivered to my inbox via messenger. We learned so much, and I had a great time with it. Big &lt;em&gt;thank you&lt;/em&gt; to all the participants for making this experiment a success 🙏 🎉. Couldn&amp;rsquo;t have done it at all without you.&lt;/p&gt;
&lt;h3 id=&#34;next-steps&#34;&gt;Next steps&lt;/h3&gt;
&lt;p&gt;You can 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-01-24-peer-learning-group-feedback/&#34;&gt;leave feedback on Peer Learning Group here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-02-07-peer-learning-group-sign-up&#34;&gt;sign up for the next Peer Learning Group here&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A Flow for Focused Reading</title>
      <link>https://davidbieber.com/snippets/2021-02-05-focused-reading/</link>
      <pubDate>Fri, 05 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-02-05-focused-reading/</guid>
      
      <description>&lt;p&gt;As you can see from the snippet you&amp;rsquo;re currently reading, I&amp;rsquo;ve implemented a simple tool to help with focused reading. (It&amp;rsquo;s 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-02-02-focused-reading-browserflow-flow-idea/&#34;&gt;the idea from the previous snippet&lt;/a&gt;). The majority of the page is dimmed, except for a few lines above and below your mouse cursor. As you move your mouse, the focused region follows. Give it a try; move your mouse (or touch) over the next paragraph, and watch as the light region follows.&lt;/p&gt;
&lt;p&gt;This is useful for staying focused when reading. If your eyes or mind wander while reading, it&amp;rsquo;s easy to quickly bring your attention back to exactly where you left off.&lt;/p&gt;
&lt;p&gt;For the 
&lt;a href=&#34;https://browserflow.app&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Browserflow&lt;/a&gt; users among you (psst&amp;hellip; DK, you need to ship Browserflow so there &lt;em&gt;are&lt;/em&gt; Browserflow users out there), you can enable this effect on any page using 
&lt;a href=&#34;https://browserflow.app/shared/8c2f3de8-2666-4578-8b42-58f5cad105b0&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;this BrowserFlow flow I made&lt;/a&gt;. Once you get the flow you can simply type cmd-J and select &amp;ldquo;Focus Bar&amp;rdquo; from the typeahead to enable this effect anywhere.&lt;/p&gt;
&lt;p&gt;For everyone else, you can paste this script into your JavaScript console. 🤷&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;var mouseY = 0;
var scrollY = 0;
var offset = 50;
var div_below, div_above;

div_below = document.createElement(&amp;quot;div&amp;quot;);
div_below.style.position = &amp;quot;absolute&amp;quot;;
div_below.style.left = &amp;quot;0px&amp;quot;;
div_below.style.top = &amp;quot;0px&amp;quot;;
div_below.style.width = &amp;quot;100%&amp;quot;;
div_below.style.height = &amp;quot;100%&amp;quot;;
div_below.style.background = &amp;quot;black&amp;quot;;
div_below.style.opacity = &amp;quot;30%&amp;quot;;

div_above = document.createElement(&amp;quot;div&amp;quot;);
div_above.style.position = &amp;quot;absolute&amp;quot;;
div_above.style.left = &amp;quot;0px&amp;quot;;
div_above.style.bottom = &amp;quot;0px&amp;quot;;
div_above.style.width = &amp;quot;100%&amp;quot;;
div_above.style.height = &amp;quot;100%&amp;quot;;
div_above.style.background = &amp;quot;black&amp;quot;;
div_above.style.opacity = &amp;quot;30%&amp;quot;;

document.body.appendChild(div_below);
document.body.appendChild(div_above);

function adjust_divs() {
  scrollY = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
  div_below.style.top = (mouseY + offset + scrollY) + &#39;px&#39;;
  div_above.style.bottom = (
      &#39;calc(100% - &#39; + (mouseY - offset + scrollY) + &#39;px&#39;);
  div_below.style.height = (
      &#39;calc(100% - &#39; + (mouseY + offset) + &#39;px&#39;);
}

document.addEventListener(&#39;mousemove&#39;, function(event) {
  mouseY = event.clientY;
  adjust_divs();
}, true);

document.addEventListener(&#39;scroll&#39;, function(event) {
  adjust_divs();
}, true);
document.addEventListener(&#39;touchstart&#39;, function(event) {
  mouseY = event.touches[0].clientY;
  adjust_divs();
}, true);
document.addEventListener(&#39;touchmove&#39;, function(event) {
  mouseY = event.touches[0].clientY;
  adjust_divs();
}, true);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sorry about the jitter. Let me know if you know how to fix it.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Focused Reading Browserflow Flow Idea</title>
      <link>https://davidbieber.com/snippets/2021-02-02-focused-reading-browserflow-flow-idea/</link>
      <pubDate>Tue, 02 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-02-02-focused-reading-browserflow-flow-idea/</guid>
      
      <description>&lt;p&gt;This idea for an assistive technology for focused reading comes from 
&lt;a href=&#34;https://accessibe.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;accessiBe&lt;/a&gt;. I stumbled upon it on 
&lt;a href=&#34;https://www.tasteofhome.com/recipes/homemade-potato-chips/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;tasteofhome.com&lt;/a&gt;. The idea is to make the web more accessible to folks with ADHD by dimming the part of the screen they&amp;rsquo;re not actively looking at.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a video of the accessiBe implementation in action on the tasteofhome.com website.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://firebasestorage.googleapis.com/v0/b/firescript-577a2.appspot.com/o/imgs%2Fapp%2Fplayground%2FbF12xbo8EB.gif?alt=media&amp;amp;token=d1cc35a1-8354-4859-9415-7a48e5283310&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;As you can see, the screen is dimmed everywhere except on the lines surrounding the mouse pointer. This helps me to regain focus more quickly if my attention is drawn away from the text I was reading.&lt;/p&gt;
&lt;p&gt;I find this way of reading helpful, and so I&amp;rsquo;m thinking about making it for myself as a Browserflow flow. It should be easy enough to do. When the flow starts, it just has to add two large transparent rectangles to the DOM, and an event handler to update their positions whenever my mouse moves.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll put up another snippet if and when I build this.&lt;/p&gt;
&lt;p&gt;Update Feb 5, 2021: As you may have noticed, I&amp;rsquo;ve now implemented this idea. It&amp;rsquo;s enabled on this page, and also available as a Browserflow flow. 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-02-05-focused-reading&#34;&gt;See the snippet here&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Asking for upvotes</title>
      <link>https://davidbieber.com/snippets/2021-01-31-asking-for-upvotes/</link>
      <pubDate>Sun, 31 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-31-asking-for-upvotes/</guid>
      
      <description>&lt;p&gt;Hello! Can I let you know when I post new content? In particular, can I let you know when I post things to e.g. Hacker News, which require upvotes to be seen? This should go without saying: there&amp;rsquo;s no pressure to actually upvote anything &amp;ndash; but if you think my submission deserves it and you do upvote it, that&amp;rsquo;s much appreciated!&lt;/p&gt;
&lt;p&gt;If &lt;em&gt;Yes&lt;/em&gt;, let me know. You can let me know 
&lt;a href=&#34;https://www.messenger.com/t/dbieber&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;on Facebook messenger&lt;/a&gt;, or you can fill out this form. Info about the &lt;em&gt;content-sharing group&lt;/em&gt; option below the fold.&lt;/p&gt;
&lt;iframe src=&#34;https://docs.google.com/forms/d/e/1FAIpQLSeKINUItuKwpf_wG221Q2c-QnntQabeXTGPFtzUrhlF9H6qvw/viewform?embedded=true&#34; width=&#34;640&#34; height=&#34;765&#34; frameborder=&#34;0&#34; marginheight=&#34;0&#34; marginwidth=&#34;0&#34;&gt;Loading…&lt;/iframe&gt;
&lt;p&gt;&amp;ldquo;What&amp;rsquo;s a &lt;em&gt;content-sharing group&lt;/em&gt;?&amp;rdquo;, you may be wondering. It&amp;rsquo;s a small Facebook messenger group where the social norm is to share your creative output. This is a place to share things you&amp;rsquo;ve made, posts you&amp;rsquo;ve written, or progress updates on your latest side-project. All sharing of this kind is welcome. Feel free to brag. Incremental updates are welcome too, so there&amp;rsquo;s no need to wait until a project is finished. It&amp;rsquo;s not spamming; it&amp;rsquo;s what the group is for! To join, just let me know or fill out the form and I&amp;rsquo;ll add you.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>SQL for the Kangaroo Auto-responder</title>
      <link>https://davidbieber.com/snippets/2021-01-30-sql-for-the-kangaroo-auto-responder/</link>
      <pubDate>Sat, 30 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-30-sql-for-the-kangaroo-auto-responder/</guid>
      
      <description>&lt;p&gt;I turned on the 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-01-29-kangaroo-auto-responder/&#34;&gt;Kangaroo Auto-responder&lt;/a&gt; this morning. The rules for when to send a kangaroo 🦘 are as follows:&lt;/p&gt;
&lt;p&gt;You get a kangaroo if the &lt;strong&gt;most-recent&lt;/strong&gt; message in our chat (ignoring trivial messages from you) is &lt;strong&gt;non-trivial&lt;/strong&gt;, &lt;strong&gt;read-by-me&lt;/strong&gt;, &lt;strong&gt;written-by-you&lt;/strong&gt;, &lt;strong&gt;not a response&lt;/strong&gt;, and &lt;strong&gt;eight-hours old&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s look at each of these criteria in more detail.&lt;/p&gt;
&lt;h2 id=&#34;most-recent-message&#34;&gt;Most-recent message&lt;/h2&gt;
&lt;p&gt;The criteria are being applied to the most recent message in our chat ignoring trivial messages from you.&lt;/p&gt;
&lt;p&gt;In SQL, this looks like&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select thread_id, max(timestamp) as timestamp
from messenger
where (author = &#39;1409114395&#39; or (author &amp;lt;&amp;gt; &#39;1409114395&#39; and LENGTH(text) &amp;gt; 15))
group by thread_id;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;1409114395 is my Facebook ID.&lt;/p&gt;
&lt;p&gt;This query selects the most recent timestamp from only a single message in each thread. It considers all messages from me, but only non-trivial (more than 15 characters) messages from the other participant.&lt;/p&gt;
&lt;p&gt;The reason for this is that if I have sent the most recent message in a conversation (regardless of the length of the message), then no kangaroo is needed. If the other person has sent the most recent message, a kangaroo might be in order, but trivial messages should not trigger kangaroos. So we ignore them, and see if the most recent message is still from the other person even when ignoring their trivial messages.&lt;/p&gt;
&lt;h2 id=&#34;non-trivial&#34;&gt;Non-trivial&lt;/h2&gt;
&lt;p&gt;We choose 15-characters as the threshold for what makes a message trivial. The reason we ignore trivial messages is because they often don&amp;rsquo;t warrant a response. I am considering removing this constraint, as the &amp;ldquo;Not a response&amp;rdquo; constraint seems to obviate the need for it.&lt;/p&gt;
&lt;p&gt;This shows up as &lt;code&gt;LENGTH(text) &amp;gt; 15)&lt;/code&gt; in the query.&lt;/p&gt;
&lt;h2 id=&#34;read-by-me&#34;&gt;Read-by-me&lt;/h2&gt;
&lt;p&gt;Unfortunately I do not have read receipt information in my messages database, so I did not include this rule in the first version of the Kangaroo Auto-responder.&lt;/p&gt;
&lt;h2 id=&#34;written-by-you&#34;&gt;Written-by-you&lt;/h2&gt;
&lt;p&gt;Only if the most recent message is from you is a kangaroo necessary. If its from me, I&amp;rsquo;ve already responded!&lt;/p&gt;
&lt;p&gt;In this query, this is a simple check:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;WHERE messenger.author &amp;lt;&amp;gt; &#39;1409114395&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;not-a-response&#34;&gt;Not-a-response&lt;/h2&gt;
&lt;p&gt;This is an interesting piece. When I wrote out the rules for the auto-responder yesterday, I was thinking I&amp;rsquo;d ignore messages sent within 5 minutes of a message I sent. My thinking was that this small filter would prevent me from needing to get the last word in every conversation to avoid oversending of kangaroos.&lt;/p&gt;
&lt;p&gt;Now, I&amp;rsquo;m thinking I&amp;rsquo;ll ignore messages sent within &lt;em&gt;36 hours&lt;/em&gt; of a message I sent. This is a much tighter restriction. It means that I may miss sending some kangaroos that I ought to have sent, but it also means that if someone takes two hours to reply to me and that&amp;rsquo;s the end of the conversation, I don&amp;rsquo;t need to reply to prevent a kangaroo from going out.&lt;/p&gt;
&lt;p&gt;It seems like striking a good balance between the non-trivial message criteria and the not-a-response criteria is key, and I may adjust these going forward.&lt;/p&gt;
&lt;p&gt;To determine if a message is a response, I first determine the time of my own most recent message in the chat. In SQL, this is:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select thread_id, max(timestamp) as outgoing_timestamp
from messenger
where author = &#39;1409114395&#39; -- my FB id
group by thread_id;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I then compare this message&amp;rsquo;s timestamp with that of the most recent message in the thread, which we selected earlier:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;(  -- The reply is at least X minutes after my latest message.
  (latest_messages.timestamp - outgoing_timestamp)/1000 &amp;gt; 36*60*60
  or outgoing_timestamp IS NULL
)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;8-hours-old&#34;&gt;8-hours old&lt;/h2&gt;
&lt;p&gt;The final criteria for whether to send a kangaroo is that the message must be eight hours old. Yesterday I was initially planning for 2-hours old, but I decided to give myself more time to respond manually before the kangaroo would go out. Here&amp;rsquo;s the SQL for that:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;-- Message is 8 hours old:
AND NOW() - to_timestamp(messenger.timestamp/1000) at time zone &#39;UTC&#39; &amp;gt; INTERVAL &#39;8 HOURS&#39;
AND NOW() - to_timestamp(messenger.timestamp/1000) at time zone &#39;UTC&#39; &amp;lt; INTERVAL &#39;8.25 HOURS&#39;

&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;putting-it-all-together&#34;&gt;Putting it all together&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s the complete SQL query that finds messages which warrant an automated kangaroo response.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;-- Select the most recent message per thread
-- (ignoring trivial messages from you),
-- and the most recent message per thread specifically from me.
-- If the most recent message (ignoring trivial messages from you)
-- is non-trivial,
-- written-by-you,
-- not a reply to my message,
-- and a specific age,
-- then we&#39;ve got ourselves a Kangaroo!
--
-- In a future iteration we will also ensure the message has been read-by-me.

SELECT * FROM

-- The first sub-query:
-- Selects the most recent message from each thread that is either:
-- (A) from me, or (B) from you and non-trivial in length
-- And is also less than 8 hours old.
((select thread_id, max(timestamp) as timestamp
 from messenger
 where (author = &#39;1409114395&#39; or (author &amp;lt;&amp;gt; &#39;1409114395&#39; and LENGTH(text) &amp;gt; 15))
 -- and to_timestamp(timestamp/1000) at time zone &#39;UTC&#39; &amp;gt; NOW() - INTERVAL &#39;800 HOURS&#39;
 group by thread_id) AS latest_messages
INNER JOIN
  messenger
ON
  messenger.thread_id = latest_messages.thread_id AND
  messenger.timestamp = latest_messages.timestamp)
LEFT JOIN
    -- Selects the most recent message from each thread from me:
    (select thread_id, max(timestamp) as outgoing_timestamp
     from messenger
     where author = &#39;1409114395&#39;
     -- and to_timestamp(timestamp/1000) at time zone &#39;UTC&#39; &amp;gt; NOW() - INTERVAL &#39;800 HOURS&#39;
     group by thread_id) AS latest_outgoing_messages
ON
  messenger.thread_id = latest_outgoing_messages.thread_id
WHERE messenger.author &amp;lt;&amp;gt; &#39;1409114395&#39; -- David Bieber
AND messenger.author &amp;lt;&amp;gt; &#39;1985867351654140&#39; -- Bieber Bot
AND (  -- The reply is at least X minutes after my latest message.
  (latest_messages.timestamp - outgoing_timestamp)/1000 &amp;gt; 36*60*60
  or outgoing_timestamp IS NULL
)
AND thread_type = &#39;USER&#39; -- Message is a 1:1 chat, not a group chat
-- Message is 8 hours old:
AND NOW() - to_timestamp(messenger.timestamp/1000) at time zone &#39;UTC&#39; &amp;gt; INTERVAL &#39;8 HOURS&#39;
AND NOW() - to_timestamp(messenger.timestamp/1000) at time zone &#39;UTC&#39; &amp;lt; INTERVAL &#39;8.25 HOURS&#39;
ORDER BY messenger.timestamp desc;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This checks all the criteria for whether a message needs a kangaroo. I&amp;rsquo;ve set up a script that runs this query every ten minutes, and sends kangaroos as necessary.&lt;/p&gt;
&lt;p&gt;At the time of this writing, no kangaroos have been sent yet. I hope it works 🤞!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Kangaroo Auto-responder</title>
      <link>https://davidbieber.com/snippets/2021-01-29-kangaroo-auto-responder/</link>
      <pubDate>Fri, 29 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-29-kangaroo-auto-responder/</guid>
      
      <description>&lt;p&gt;The purpose of the Kangaroo Auto-responder is to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Avoid people expecting a response from me when I don&amp;rsquo;t realize they&amp;rsquo;re expecting a response, e.g. because I&amp;rsquo;ve forgotten about their message&lt;/li&gt;
&lt;li&gt;It should let me let my guard down a bit about feeling obligated to respond to people&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;What will it do?&lt;/p&gt;
&lt;p&gt;It will automatically respond to messages that I&amp;rsquo;ve seen but haven&amp;rsquo;t responded to for 2+ hours with a kangaroo&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;The first time it sends someone a kangaroo, it will also explain:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;[Kangaroo] Hello! This is an automated reply from the Kangaroo Auto-responder. You&amp;rsquo;re getting this message because it looks like David might forget to reply to your message. If you want a response, you should contact him again. (Just saying &amp;ldquo;ping&amp;rdquo; is often enough!)&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Text for the second time:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;[Kangaroo] Me again. David might forget to reply to your message. In the future I&amp;rsquo;ll just send you a picture of a Kangaroo to symbolize this. 🦘  If you ever get a picture of a Kangaroo from me, it just means David may have dropped the ball on your message and you should contact him again if you&amp;rsquo;re expecting a response.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Subsequent kangaroos will be unaccompanied by explanations.&lt;/p&gt;
&lt;p&gt;The details on exactly when to send kangaroos are still a work in progress. I don&amp;rsquo;t want to overwhelm anyone with kangaroos. I&amp;rsquo;m thinking about some rules: (1) only send kangaroos if there was a message of non-trivial length, e.g. more than 20 characters, (2) only send a kangaroo after I&amp;rsquo;ve read the message; if I genuinely haven&amp;rsquo;t seen the message yet, no need for a kangaroo, as the message will still appear as unread in my inbox, (3) if you send follow-up messages, that resets the timer on the 2 hours, (4) any messages you send within 5 minutes of me sending you a message are ineligible for triggering kangaroos (this way I don&amp;rsquo;t need to get the last word), and (5) obviously, don&amp;rsquo;t send a kangaroo for a message I&amp;rsquo;ve already responded too.&lt;/p&gt;
&lt;p&gt;To summarize, the rules of kangaroos are: You get a kangaroo if the &lt;strong&gt;most-recent&lt;/strong&gt; message in our chat is &lt;strong&gt;non-trivial&lt;/strong&gt;, &lt;strong&gt;read-by-me&lt;/strong&gt;, &lt;strong&gt;written-by-you&lt;/strong&gt;, &lt;strong&gt;not an immediate reply&lt;/strong&gt;, and &lt;strong&gt;two-hours old&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Why kangaroos? They bounce 🤷‍♂️ ? This is kind of like a message bouncing&amp;hellip;&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;With a picture of a kangaroo, that is. Like this one: 🦘, or this: &lt;img src=&#34;https://firebasestorage.googleapis.com/v0/b/firescript-577a2.appspot.com/o/imgs%2Fapp%2Fplayground%2FtBz98tV75N.png?alt=media&amp;amp;token=66762cac-d0b0-43ba-91a8-eaefa6ef7626&#34; alt=&#34;&#34;&gt; It will not send them an actual real-life kangaroo. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Notifications in Roam Research</title>
      <link>https://davidbieber.com/snippets/2021-01-25-notifications-in-roam-research/</link>
      <pubDate>Mon, 25 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-25-notifications-in-roam-research/</guid>
      
      <description>&lt;p&gt;
&lt;a href=&#34;https://twitter.com/hashtag/RoamGames&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;#RoamGames&lt;/a&gt; are upon us! The challenge: &lt;em&gt;project management&lt;/em&gt; in Roam.&lt;/p&gt;
&lt;p&gt;So, let&amp;rsquo;s talk notifications. They&amp;rsquo;re going to be essential for any multiplayer Roam scenario. They&amp;rsquo;re also ruthless attention vampires that kill productivity. We&amp;rsquo;ve got to get this right.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s disentangle &lt;em&gt;what&lt;/em&gt; you get notified about, &lt;em&gt;when&lt;/em&gt; you get notified about it, and &lt;em&gt;where/how&lt;/em&gt; you&amp;rsquo;re notified. This leads us to a vision where users can define &lt;em&gt;notification strategies&lt;/em&gt; and take control of their attention&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&#34;what-to-notify-on-references-and-queries&#34;&gt;&lt;strong&gt;What&lt;/strong&gt; to notify on (References and Queries)&lt;/h2&gt;
&lt;p&gt;What do we want to get notified about? First, three scenarios to motivate our discussion. Then, the primitives: references and queries.&lt;/p&gt;
&lt;h4 id=&#34;scenario-1-chat&#34;&gt;Scenario 1, Chat:&lt;/h4&gt;
&lt;p&gt;You&amp;rsquo;re working on Secret Project X, conversing asynchronously with your teammate Abhay about Feature XX. It&amp;rsquo;s gonna be big. While you&amp;rsquo;re off working on something else Abhay responds to a bunch of your earlier messages. You want to get notified about this, for sure.&lt;/p&gt;
&lt;h4 id=&#34;scenario-2-blockers&#34;&gt;Scenario 2, Blockers:&lt;/h4&gt;
&lt;p&gt;You&amp;rsquo;re working on Task A. But it&amp;rsquo;s blocked by Tasks B and C. You represent this in your Roam graph like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://firebasestorage.googleapis.com/v0/b/firescript-577a2.appspot.com/o/imgs%2Fapp%2Fplayground%2FjLpcHwI9aQ.png?alt=media&amp;amp;token=eeb11581-2466-4824-a725-35a0bd720eff&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;(As an aside, being able to embed a tiny piece of my Roam graph in my blog would be super helpful.)&lt;/p&gt;
&lt;p&gt;Once Task B and Task C are marked DONE, you want to get notified so you can resume working on Task A.&lt;/p&gt;
&lt;h4 id=&#34;scenario-3-topic-tracking&#34;&gt;Scenario 3, Topic Tracking:&lt;/h4&gt;
&lt;p&gt;You&amp;rsquo;re in a big multiplayer graph and you&amp;rsquo;ve carefully curated a page about your own project 
&lt;a href=&#34;https://github.com/google/python-fire&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Python Fire&lt;/a&gt;. You&amp;rsquo;re excited when people talk about Fire, so you want notifications when people reference it.&lt;/p&gt;
&lt;h4 id=&#34;the-primitives-references-and-queries&#34;&gt;The Primitives: References and Queries&lt;/h4&gt;
&lt;p&gt;Basic usage: Notifications when someone responds to me&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;, notifications when someone references a particular page or block (linked or unlinked)&lt;/p&gt;
&lt;p&gt;Advanced usage: Roam queries and Datalog queries&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; are extremely expressive. I should be able to set up a query and get notified whenever the query results change.&lt;/p&gt;
&lt;p&gt;Now that we&amp;rsquo;ve set out what we want to get notified about, let&amp;rsquo;s talk about when we want to receive the notifications. We&amp;rsquo;ll get to how we want to configure the notifications a little bit later on.&lt;/p&gt;
&lt;h2 id=&#34;when-to-notify-immediately-batched-delayed-at-specific-times&#34;&gt;&lt;strong&gt;When&lt;/strong&gt; to notify (Immediately, Batched, Delayed, At specific times?)&lt;/h2&gt;
&lt;p&gt;Most apps have minimal options for when you receive notifications. A typical message board config offers &amp;ldquo;every individual email&amp;rdquo;, &amp;ldquo;daily digest&amp;rdquo;, &amp;ldquo;weekly digest.&amp;rdquo; This is Roam. We can do better than that.&lt;/p&gt;
&lt;p&gt;For the messages from Abhay about Project XX, I want notifications to pop up immediately.&lt;/p&gt;
&lt;p&gt;When I become unblocked on a task, I want a notification within the hour, but if multiple tasks become unblocked they the notifications can totally be bundled. I don&amp;rsquo;t need an &lt;em&gt;individual notification&lt;/em&gt; per task. That would just be overkill.&lt;/p&gt;
&lt;p&gt;And for references to Python Fire, a daily digest at 9am is more than sufficient.&lt;/p&gt;
&lt;h4 id=&#34;primitive-notification-strategies&#34;&gt;Primitive: Notification Strategies&lt;/h4&gt;
&lt;p&gt;Anyone with a bit of JavaScript or Clojure knowledge can define a notification strategy. A notification strategy defines the rules for how notifications should be handled. The interface for a notification strategy is: stream of notifications in, stream of notifications out.&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;By allowing users to define and share notification strategies, we can empower uses to take back their attention and get more out of their Roam experience.&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;Notification strategies&amp;rdquo; approach benefits non-programmers too, because notification strategies can be shared in the Roam Depot&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;. I&amp;rsquo;m hoping for a future where RoamHacker and David Vargas and others have developed both simple and sophisticated &amp;ldquo;notification managers&amp;rdquo;: UIs where non-programmers can configure their notification settings in the level of detail best suited for them.&lt;/p&gt;
&lt;h4 id=&#34;primitive-tags-connect-references-and-queries-to-notification-strategies&#34;&gt;Primitive: Tags connect references and queries to notification strategies&lt;/h4&gt;
&lt;p&gt;That is, tags connect &lt;em&gt;what&lt;/em&gt; to &lt;em&gt;when&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;When you write a notification strategy, you name it. Tag a reference of a query with the name of a notification strategy to run that strategy on that reference or query.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s clarify with an example.&lt;/p&gt;
&lt;p&gt;Say I have a query (&amp;ldquo;all Tasks with &amp;lsquo;Blockers&amp;rsquo; where all Blockers are &amp;lsquo;DONE&amp;rsquo;&amp;quot;), and a notification strategy named &amp;ldquo;Bundle on the Hour&amp;rdquo; (&amp;ldquo;bundle all incoming notifications and emit them on the hour as a single notification&amp;rdquo;). Then I can tag the query with #[[Bundle on the Hour]] to start applying that notification strategy to the results of the query.&lt;/p&gt;
&lt;p&gt;Once I&amp;rsquo;ve added that tag, the notification strategy will be called every time the query results change, and it will be able to start emitting notifications.&lt;/p&gt;
&lt;p&gt;Similarly if I write [[Python Fire]] and tag it with #[[Digest at 9am]], then &lt;em&gt;that&lt;/em&gt; notification strategy will be called whenever the references to or contents of the Python Fire page change.&lt;/p&gt;
&lt;h2 id=&#34;wherehow-actually-sending-notifications&#34;&gt;&lt;strong&gt;Where/How&lt;/strong&gt;: Actually sending notifications&lt;/h2&gt;
&lt;p&gt;Great, we&amp;rsquo;ve talked about how to decide what to notify about, and when to send the notifications. How/where do the notifications actually get sent?&lt;/p&gt;
&lt;p&gt;A sensible default for the first pass is to use browser notifications. But we&amp;rsquo;re thinking long term, so I won&amp;rsquo;t dwell on this &amp;ldquo;first pass&amp;rdquo; for too long.&lt;/p&gt;
&lt;p&gt;If you do want to use browser notifications, it&amp;rsquo;s easy to do so&lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;. You can try this in your Roam graph (or browser console&lt;sup id=&#34;fnref:7&#34;&gt;&lt;a href=&#34;#fn:7&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;7&lt;/a&gt;&lt;/sup&gt;) right now:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;function notify(text) {
  // Let&#39;s check if the browser supports notifications
  if (!(&amp;quot;Notification&amp;quot; in window)) {
    alert(text);
  }

  // Let&#39;s check whether notification permissions have already been granted
  else if (Notification.permission === &amp;quot;granted&amp;quot;) {
    // If it&#39;s okay let&#39;s create a notification
    var notification = new Notification(text);
  }

  // Otherwise, we need to ask the user for permission
  else if (Notification.permission !== &amp;quot;denied&amp;quot;) {
    Notification.requestPermission().then(function (permission) {
      // If the user accepts, let&#39;s create a notification
      if (permission === &amp;quot;granted&amp;quot;) {
        var notification = new Notification(text);
      } else {
        console.log(text);
      }
    });
  } else {
    // At last, if the user has denied notifications, and you
    // want to be respectful there is no need to bother them any more.
    console.log(text);
  }
}

notify(&amp;quot;You&#39;ve got mail.&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I don&amp;rsquo;t want browser notifications though. I want my personal digital assistant 
&lt;a href=&#34;https://davidbieber.com/projects/bieber-bot/&#34;&gt;Bieber Bot&lt;/a&gt; to send me notifications. Now, this is no trouble in a private graph. I can use a webhook to send myself a message as Bieber Bot. In a public graph, however, this would be dangerous. Anyone could see the code and start impersonating Bieber Bot. A travesty!&lt;/p&gt;
&lt;p&gt;So, we need Roam to support &lt;em&gt;secrets&lt;/em&gt;. Ideally this would come from the Roam core team, not the community. First class secrets would enable me to write roam/js that communicates securely with my own services, like Bieber Bot and others, without giving other users the capability of doing the same.&lt;/p&gt;
&lt;p&gt;As an alternative approach to secrets, having all Roam graphs be &lt;em&gt;one giant graph&lt;/em&gt; with a good permissions model would also be sufficient. Then I could put my notifier code in my graph (private), but have the queries that trigger the notifier apply to a graph I share with my team.&lt;/p&gt;
&lt;p&gt;How does specifying a notifier (browser notifications vs Bieber Bot) fit in with writing queries and enabling notifications? You can set your default &amp;ldquo;notify&amp;rdquo; function just by defining the function &amp;ldquo;notify&amp;rdquo; and tagging it / nesting it under roam/notify. You can also set a notify function whenever you define notifications just by adding an extra reference with the name of the notify function.&lt;/p&gt;
&lt;h2 id=&#34;some-examples&#34;&gt;Some Examples&lt;/h2&gt;
&lt;p&gt;This was a lot, and reading the above it might sound complicated. And that&amp;rsquo;s because it &lt;em&gt;can&lt;/em&gt; be complicated; you can have as complicated a notification strategy as you like. But it doesn&amp;rsquo;t have to be complicated, and for most users it won&amp;rsquo;t be.&lt;/p&gt;
&lt;p&gt;Ideally turning on notifications for messages could be as simple as adding a block in your graph that says:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[[roam/messages]] #[[Notify me immediately]]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Turning on notifications for unblocked tasks could be as simple as (1) getting the unblocked tasks query from the Roam Depot, and then (2) adding a block &lt;code&gt;[[Unblocked tasks]] #[[Bundle on the Hour]]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And turning on notifications for references to Python Fire should simply mean adding a block &lt;code&gt;[[Python Fire]] #[[Digest at 9am]]&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;lets-build-it&#34;&gt;Let&amp;rsquo;s build it&lt;/h2&gt;
&lt;p&gt;Want to build this with me? I&amp;rsquo;m 
&lt;a href=&#34;https://twitter.com/Bieber&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;@Bieber&lt;/a&gt; on Twitter and active as dbieber on the 
&lt;a href=&#34;https://roamresearch.slack.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Roam Slack&lt;/a&gt;.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;And still provides sensible defaults and easy configs for non-power users. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;This one, while a basic use case, is actually tricky to express as a query. But we can do it, I&amp;rsquo;m confident. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;See my 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-12-22-datalog-queries-for-roam-research/&#34;&gt;two&lt;/a&gt; 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-01-04-more-datalog-queries-for-roam/&#34;&gt;snippets&lt;/a&gt; for lots of examples of what you can do with datalog queries. &lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;em&gt;soni-sono&lt;/em&gt; for short. &lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Has anyone taken the 
&lt;a href=&#34;https://fontmeme.com/the-home-depot-font/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Home Depot logo&lt;/a&gt; and replaced the word Home with Roam in the appropriate font yet? &lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:6&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Code courtesy of 
&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/API/notification&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;MDN&lt;/a&gt;. &lt;a href=&#34;#fnref:6&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:7&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;cmd-option-i to open your browser console on Chrome on Mac. 
&lt;a href=&#34;https://www.google.com/search?q=how&amp;#43;to&amp;#43;open&amp;#43;the&amp;#43;browser&amp;#43;console&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Look it up here&lt;/a&gt; for other browsers or operating systems. &lt;a href=&#34;#fnref:7&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Peer Learning Group Feedback</title>
      <link>https://davidbieber.com/snippets/2021-01-24-peer-learning-group-feedback/</link>
      <pubDate>Sun, 24 Jan 2021 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-24-peer-learning-group-feedback/</guid>
      
      <description>&lt;p&gt;You can use this form to submit feedback about the January 25, 2021 - February 7, 2021 Peer Learning Group. Make sure to leave your name or email if you want a response, otherwise its anonymous. You can also 
&lt;a href=&#34;https://messenger.com/t/dbieber&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;message me directly&lt;/a&gt;.&lt;/p&gt;
&lt;iframe src=&#34;https://docs.google.com/forms/d/e/1FAIpQLSe3kh5uq6OFLakI4Uf7GEMn0POuDqfMUwumKactjHaixfdEAQ/viewform?embedded=true&#34; width=&#34;640&#34; height=&#34;545&#34; frameborder=&#34;0&#34; marginheight=&#34;0&#34; marginwidth=&#34;0&#34;&gt;Loading…&lt;/iframe&gt;
</description>
    </item>
    
    <item>
      <title>Margin notes</title>
      <link>https://davidbieber.com/snippets/2021-01-23-margin-notes/</link>
      <pubDate>Sat, 23 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-23-margin-notes/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;d like to add margin notes to my website.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
I&amp;rsquo;d also like to learn how to use Fiverr.&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;
So, I&amp;rsquo;m going to hire someone on Fiverr to add margin notes on my website.&lt;/p&gt;
&lt;p&gt;Fabian, over at capnfabs.net, has an 
&lt;a href=&#34;https://capnfabs.net/posts/margin-notes-hugo-theme/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;excellent post&lt;/a&gt; where he adds margin notes to his own hugo blog. We&amp;rsquo;ll be using that for guidance.&lt;/p&gt;
&lt;p&gt;After my Fiverr experience I&amp;rsquo;ll update this snippet or add a new one, ideally one full of margin notes.&lt;/p&gt;
&lt;p&gt;Update (same day): I&amp;rsquo;m back! I didn&amp;rsquo;t use Fiverr. I used the post on capnfabs for reference and set up margin notes myself. Thank you Fabian for documenting your process.&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; I&amp;rsquo;ll have to learn to use Fiverr another day.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m glad to have this working. There&amp;rsquo;s room to improve the style though. Perhaps in a future iteration I&amp;rsquo;ll move the main content left to give more space for the margin notes, or make some changes to the font and size.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I&amp;rsquo;d like this to be a margin note. At the time of this writing, it&amp;rsquo;s a footnote. &lt;em&gt;Update&lt;/em&gt;: Now it&amp;rsquo;s a margin note! At least if your browser is wide enough&amp;hellip; otherwise it&amp;rsquo;s still a footnote. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I&amp;rsquo;ve used it twice before, but I didn&amp;rsquo;t have a great experience with the one programmer I hired. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Really, it is greatly appreciated! 🙏 &lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>am I available for conversation right now dot com</title>
      <link>https://davidbieber.com/snippets/2021-01-22-am-i-available-for-conversation-right-now-dot-com/</link>
      <pubDate>Fri, 22 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-22-am-i-available-for-conversation-right-now-dot-com/</guid>
      
      <description>&lt;p&gt;I don&amp;rsquo;t know if I like this idea, but I&amp;rsquo;m giving it a try; I&amp;rsquo;ve added a &amp;ldquo;Now&amp;rdquo; page to my website (
&lt;a href=&#34;https://davidbieber.com/now/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;davidbieber.com/now&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The idea for now pages is described at &lt;a href=&#34;https://nownownow.com/about&#34;&gt;https://nownownow.com/about&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Basically, a now page says what&amp;rsquo;s going on in the author&amp;rsquo;s life now. Not &lt;em&gt;right now&lt;/em&gt; &amp;ndash; that would be a &amp;ldquo;right now page&amp;rdquo; &amp;ndash; but rather, now in the broader sense of &amp;ldquo;what&amp;rsquo;s are you up to these days?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;This post isn&amp;rsquo;t about my new Now page though, which I don&amp;rsquo;t necessarily plan to keep up (if the link 404s, you know why). Rather, this post is about an idea for a kind of &amp;ldquo;right now&amp;rdquo; page that I&amp;rsquo;m toying with building.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like to make a page that tells the reader if I&amp;rsquo;m likely available for a conversation &lt;em&gt;right now&lt;/em&gt;. I&amp;rsquo;d call it the &amp;ldquo;is David available to talk now&amp;rdquo; page, and here&amp;rsquo;s how it might work.&lt;/p&gt;
&lt;h3 id=&#34;it-aims-only-to-give-a-best-guess-as-to-whether-i-can-talk-now&#34;&gt;It aims only to give a best guess as to whether I can talk now.&lt;/h3&gt;
&lt;p&gt;It says No during work.&lt;br/&gt;
It says No during sleep hours.&lt;br/&gt;
It says No while I&amp;rsquo;m on a phone call / skype / zoom / meet etc&lt;br/&gt;
It says No if I have recently been on a call for a long time&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;It says Yes during explicitly set times (there would be a button I can press to set it to Yes for 30 minutes)&lt;/p&gt;
&lt;p&gt;If I&amp;rsquo;m deliberately in a public space (e.g. Gather Town, Clubhouse) AND looking for conversation (aka I&amp;rsquo;ve pushed the button), then it shows where to find me.&lt;/p&gt;
&lt;p&gt;And the rest of the time, it simply shrugs.&lt;/p&gt;
&lt;h3 id=&#34;why-would-i-want-such-a-system&#34;&gt;Why would I want such a system?&lt;/h3&gt;
&lt;p&gt;Well, what I really want is for &lt;em&gt;everyone&lt;/em&gt; to use such a system. I want the &amp;ldquo;open door&amp;rdquo; system that professors so often use; if my door is open, you&amp;rsquo;re welcome to come in and talk. I want to avoid people avoiding saying hi because they don&amp;rsquo;t know if I&amp;rsquo;m available. And I want to avoid the mental overhead of making plans for conversations that aren&amp;rsquo;t time sensitive. Plans are tough.&lt;/p&gt;
&lt;p&gt;My ideal system for when I want to talk to someone isn&amp;rsquo;t &amp;ldquo;let&amp;rsquo;s pick a time to talk&amp;rdquo;, because that has scheduling overhead and will likely break up my day at an inconvenient time. Instead, I&amp;rsquo;d prefer a more flexible approach. When I&amp;rsquo;m free, I open my door (a digital, virtual, door). I send you a message that I&amp;rsquo;d like to talk; you see it when you&amp;rsquo;re free (because you have notifications disabled 👍). If I&amp;rsquo;m still free then, my door will still be open and we can talk. If I&amp;rsquo;ve moved on to another activity, my door will be closed and we&amp;rsquo;ll reconnect later.&lt;/p&gt;
&lt;p&gt;In the absence of doors, the &amp;ldquo;is David available to talk now&amp;rdquo; page is my idea for an approximation.&lt;/p&gt;
&lt;p&gt;But I don&amp;rsquo;t know yet how I would build it. The idea requires programmatically determining when I&amp;rsquo;ve been on the phone, in skype, in zoom, etc. I haven&amp;rsquo;t looked into how approachable these services are to work with. And I likely won&amp;rsquo;t. This is the sort of idea that, while fun to entertain, will likely need to morph considerably before it turns into a real project. Such is the nature of the Snippet.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Clubhouse feature request: save last 60 seconds</title>
      <link>https://davidbieber.com/snippets/2021-01-20-clubhouse-feature-request-save-last-60-seconds/</link>
      <pubDate>Wed, 20 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-20-clubhouse-feature-request-save-last-60-seconds/</guid>
      
      <description>&lt;p&gt;I have a feature request for Clubhouse. Zoom, Meet, Skype, if you&amp;rsquo;re listening, this is a feature request for you all too. The request is a button to save the &lt;em&gt;previous&lt;/em&gt; 60 seconds of audio. Maybe you&amp;rsquo;re interested because people will share the clips on social media and drive more traffic back to CH 📈🤷‍♂️. I just want the feature for note-taking 📝. Details follow.&lt;/p&gt;
&lt;h2 id=&#34;the-button&#34;&gt;The button&lt;/h2&gt;
&lt;p&gt;A little floppy disk save icon. 💾. Non intrusive. When clicked, it triggers a save.&lt;/p&gt;
&lt;h2 id=&#34;just-60-seconds&#34;&gt;Just 60 seconds&lt;/h2&gt;
&lt;p&gt;The previous 60 seconds of audio are saved. This means a circular buffer of 60 seconds of audio is being stored at all times.&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t just blindly save everything, because that&amp;rsquo;s a lot of data to wade through (and to store). I just want to save the good parts. So when someone says something insightful, I click save. The rest is lost to history.&lt;/p&gt;
&lt;h2 id=&#34;respecting-privacy&#34;&gt;Respecting Privacy&lt;/h2&gt;
&lt;p&gt;If no one clicks save, the audio is gone.&lt;/p&gt;
&lt;p&gt;If someone does click save, the speakers still can choose not to have their own audio saved. Since everyone&amp;rsquo;s on their own phone, it&amp;rsquo;s possible to save an audio clip with e.g. everyone-except-David&amp;rsquo;s audio, if David decides they don&amp;rsquo;t want their audio saved.&lt;/p&gt;
&lt;p&gt;Maybe David never wants their audio saved except when he explicitly allows it. That&amp;rsquo;s fine. That&amp;rsquo;s a setting.&lt;/p&gt;
&lt;h2 id=&#34;bonus-points&#34;&gt;Bonus points&lt;/h2&gt;
&lt;p&gt;Bonus points for automatic transcription. Additional bonus points for saving the audio clip and its transcription to a Roam database. Still more bonus points for allowing sharing the clips to TikTok or Instagram or wherever, but I don&amp;rsquo;t use those, so someone else will have to provide the points.&lt;/p&gt;
&lt;h2 id=&#34;prior-art&#34;&gt;Prior Art&lt;/h2&gt;
&lt;p&gt;
&lt;a href=&#34;https://obsproject.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;OBS Studio&lt;/a&gt; has a feature for recording a circular video buffer. They call it the &amp;ldquo;replay buffer.&amp;rdquo; Streamers use it for instant replays, for example. I use it myself for screen recordings sometimes, so I can decide retroactively that something was worth saving, without having to waste gigabytes of storage recording everything.&lt;/p&gt;
&lt;p&gt;There have been 
&lt;a href=&#34;https://apps.apple.com/us/app/heard/id615420427&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;apps&lt;/a&gt; for a long time now offering cameras and audio recorders with this circular buffer feature to allow capturing the past. However, it&amp;rsquo;s never been integrated into a social product before, as far as I&amp;rsquo;m aware. Clubhouse, let&amp;rsquo;s change that.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Python hoist: immediate locals only</title>
      <link>https://davidbieber.com/snippets/2021-01-18-python-hoist-locals-only/</link>
      <pubDate>Mon, 18 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-18-python-hoist-locals-only/</guid>
      
      <description>&lt;p&gt;The implementation of &lt;code&gt;hoist&lt;/code&gt; in my 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-01-16-python-hoist/&#34;&gt;earlier snippet&lt;/a&gt; returned the values of local variables of all functions called by the hoisted function. This new version only returns the locals of the hoisted function.&lt;/p&gt;
&lt;p&gt;As before, you can use it like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;def f(x):
  y = x + 1
  z = y * 2
  return z + 1

f(4) == 11
hoist(f)(4) == {&#39;x&#39;: 4, &#39;y&#39;: 5, &#39;z&#39;: 10, &#39;return&#39;: 11}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here&amp;rsquo;s another usage example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;def f(x):
  y = messy_g(x + 1)
  return y + 1

def messy_g(z):
  q = z * 9
  w = q / 3
  return w + 1

f(1) == 8
hoist(f)(1) == {&#39;x&#39;: 1, &#39;y&#39;: 7, &#39;return&#39;: 8}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice in this example that the local variables used by &lt;code&gt;messy_g&lt;/code&gt; are not returned by &lt;code&gt;hoist(f)&lt;/code&gt;. Only &lt;code&gt;f&lt;/code&gt;&amp;rsquo;s local variables are returned.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the implementation.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import functools
import inspect
import sys

def make_trace(results, f, original_trace_fn):
  def trace_local(frame, event, arg):
    # event: &#39;call&#39;, &#39;line&#39;, &#39;return&#39;, &#39;exception&#39; or &#39;opcode&#39;
    if event == &#39;line&#39;:
      arg_info = inspect.getargvalues(frame)
      results.update(arg_info.locals.copy())
    if event == &#39;return&#39;:
      arg_info = inspect.getargvalues(frame)
      values = arg_info.locals.copy()
      results.update(values)
      results[&#39;return&#39;] = arg
    if event == &#39;call&#39;:
      return original_trace_fn

  def trace_global(frame, event, arg):
    if event == &#39;call&#39;:
      info = inspect.getframeinfo(frame)
      info_parent = inspect.getframeinfo(frame.f_back)
      if info.function == f.__name__ and info_parent.function == &#39;hoisted_f__&#39;:
        return trace_local
  return trace_global


def hoist(f):

  @functools.wraps(f)
  def hoisted_f__(*args, **kwargs):
    original_trace_fn = sys.gettrace()

    results = {}
    trace_fn = make_trace(results, f, original_trace_fn)

    sys.settrace(trace_fn)
    f(*args, **kwargs)
    sys.settrace(original_trace_fn)

    return results

  return hoisted_f__
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Refrigerator insight</title>
      <link>https://davidbieber.com/snippets/2021-01-17-refrigerator-insight/</link>
      <pubDate>Sun, 17 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-17-refrigerator-insight/</guid>
      
      <description>&lt;p&gt;When looking through the food in your refrigerator, ask not &amp;ldquo;is this what I want to eat right now?&amp;rdquo;, ask &amp;ldquo;when do I want to eat this?&amp;rdquo;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Python hoist()</title>
      <link>https://davidbieber.com/snippets/2021-01-16-python-hoist/</link>
      <pubDate>Sat, 16 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-16-python-hoist/</guid>
      
      <description>&lt;p&gt;I wrote a little decorator function called &lt;code&gt;hoist&lt;/code&gt;. Calling &lt;code&gt;hoist(f)&lt;/code&gt; transforms &lt;code&gt;f&lt;/code&gt;, such that instead of returning the return value of &lt;code&gt;f&lt;/code&gt;, it returns the values of all local variables in addition to the return value of &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can use it like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;def f(x):
  y = x + 1
  z = y * 2
  return z + 1

f(4) == 11
hoist(f)(4) == {&#39;x&#39;: 4, &#39;y&#39;: 5, &#39;z&#39;: 10, &#39;return&#39;: 11}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make sense? The result of &lt;code&gt;f(4)&lt;/code&gt; is just the return value, whereas &lt;code&gt;hoist(f)(4)&lt;/code&gt; gives the values of all local variables.&lt;/p&gt;
&lt;p&gt;This can be a useful debugging tool, allowing access to the internal state of a function. It works by setting a trace function with Python&amp;rsquo;s &lt;code&gt;sys.settrace&lt;/code&gt;, as you can see in its definition.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the definition of &lt;code&gt;hoist&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import inspect
import functools


class Collection(object):
  &amp;quot;&amp;quot;&amp;quot;The full set of variables over time.&amp;quot;&amp;quot;&amp;quot;

  def __init__(self):
    self.values = {}

  def update(self, values):
    self.values.update(values)

  def set_return(self, arg):
    self.values[&#39;return&#39;] = arg

  def __repr__(self):
    return repr(self.values)


def make_trace(results, fn):
  def trace_local(frame, event, arg):
    # event: &#39;call&#39;, &#39;line&#39;, &#39;return&#39;, &#39;exception&#39; or &#39;opcode&#39;
    if event == &#39;line&#39;:
      arg_info = inspect.getargvalues(frame)
      results.update(arg_info.locals.copy())
    if event == &#39;return&#39;:
      arg_info = inspect.getargvalues(frame)
      values = arg_info.locals.copy()
      results.update(values)
      results.set_return(arg)
    if event == &#39;call&#39;:
      return fn

  def trace_global(frame, event, arg):
    if event == &#39;call&#39;:
      return trace_local
  return trace_global


def hoist(f):

  @functools.wraps(f)
  def new_f(*args, **kwargs):
    original_trace_fn = sys.gettrace()

    results = Collection()
    trace_fn = make_trace(results, original_trace_fn)

    sys.settrace(trace_fn)
    f(*args, **kwargs)
    sys.settrace(original_trace_fn)

    return results

  return new_f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Some ideas for extensions to &lt;code&gt;hoist&lt;/code&gt; follow. Feel free to go ahead and implement these.&lt;/p&gt;
&lt;p&gt;(1) Modify &lt;code&gt;hoist&lt;/code&gt; so the outputs are accessible via dot-notation.&lt;/p&gt;
&lt;p&gt;(2) Modify &lt;code&gt;hoist&lt;/code&gt; so it returns all values taken on by all variables during the execution of &lt;code&gt;f&lt;/code&gt;.
Make it so that &lt;code&gt;hoist(f)(x)[&#39;value.3&#39;]&lt;/code&gt; returns the third value taken on by the variable &lt;code&gt;value&lt;/code&gt; in the call to &lt;code&gt;f(x)&lt;/code&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Introducing Peer Learning Group</title>
      <link>https://davidbieber.com/snippets/2021-01-14-peer-learning-group/</link>
      <pubDate>Thu, 14 Jan 2021 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-14-peer-learning-group/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;Alright. I&amp;rsquo;ve been toying with this idea for months now. Perfection is the enemy of the good. It&amp;rsquo;s time to launch a peer learning experiment. Here we go.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Hello!
Peer Learning Group is an experiment for learning new things and meeting new people. And I&amp;rsquo;d love for you to join.
The experiment lasts for two weeks, and requires only a small time commitment during this period (just a few hours total).
During these two weeks, you will learn about several topics, and you will also teach the group about one or two topics yourself.
The first peer learning group session will be January 25 - February 7, 2021.
If this interests you, I encourage you to sign up here.
Additional details about &amp;ldquo;how it works&amp;rdquo; below the fold.&lt;/p&gt;
&lt;iframe src=&#34;https://docs.google.com/forms/d/e/1FAIpQLSf32hojaa3E-v0w8jHXpLThnPJUAQrnFcRHk9kCuGW7pMQZeg/viewform?embedded=true&#34; width=&#34;640&#34; height=&#34;400&#34; frameborder=&#34;0&#34; marginheight=&#34;0&#34; marginwidth=&#34;0&#34;&gt;Loading…&lt;/iframe&gt;
&lt;h2 id=&#34;how-it-works&#34;&gt;How it works&lt;/h2&gt;
&lt;p&gt;On January 25, everyone will be added to a Facebook Messenger group chat. I&amp;rsquo;m targeting a group of about 6-8 people.&lt;/p&gt;
&lt;p&gt;Behind the scenes, I will be contacting everyone to learn what they are interested in learning about. I&amp;rsquo;ll coordinate with you to figure out 1 or 2 topics for you to teach the group about. These will be topics that someone &lt;em&gt;else&lt;/em&gt; in the group is interested in. We&amp;rsquo;ll also select a day for you to do the learning and teaching.&lt;/p&gt;
&lt;p&gt;On the chosen day, you&amp;rsquo;ll be expected to spend about an hour learning about the selected topic, and sharing what you learn with the group chat. (You&amp;rsquo;re welcome to learn about the topic in advance, but that&amp;rsquo;s not required!)&lt;/p&gt;
&lt;p&gt;How you share what you&amp;rsquo;ve learned with the group is up to you, but the bar is low. There&amp;rsquo;s no expectation of putting together a lesson plan. Instead, I&amp;rsquo;m envisioning you &amp;ldquo;live tweeting&amp;rdquo; interesting things as you learn them, putting quotes, images, and explanations into the chat that you think communicate the main ideas clearly. But I&amp;rsquo;ll reiterate: how you share what you&amp;rsquo;ve learned is completely up to you, and we&amp;rsquo;re setting our expectations low.&lt;/p&gt;
&lt;p&gt;Everyone else is welcome to discuss, ask questions, share insights, etc. The chat is there for you to use how you please.&lt;/p&gt;
&lt;p&gt;Since an hour is a relatively short period of time, I&amp;rsquo;ll try to allocate topics to you that are at the fringes of your expertise already. My theory is that while an hour is fairly short, it will still be really rewarding to hear what someone else learns from a concentrated hour of study.&lt;/p&gt;
&lt;p&gt;At the end of the two week period, you&amp;rsquo;ll have &amp;ldquo;presented&amp;rdquo; once or twice, and collectively we&amp;rsquo;ll have learned about ~10 different topics in total.&lt;/p&gt;
&lt;p&gt;The goal is to meet people and learn new things, and also to have fun. So come curious and with an open mind, and we&amp;rsquo;ll do our best to make this an interesting and enjoyable two weeks.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Plugged directly into the internet</title>
      <link>https://davidbieber.com/snippets/2021-01-13-plugged-directly-into-the-internet/</link>
      <pubDate>Wed, 13 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-13-plugged-directly-into-the-internet/</guid>
      
      <description>&lt;p&gt;I don&amp;rsquo;t do a lot of social media, and so over the holidays when I became active on several online discussion platforms simultaneously, I was a bit overwhelmed. I felt like I&amp;rsquo;d been plugged directly into the internet.&lt;/p&gt;
&lt;p&gt;On the one hand, I enjoyed the conversation. I liked that there was always conversation happening. It skipped right over the step of &lt;em&gt;initiating&lt;/em&gt; a conversation, which requires an activation energy to cross. And it eliminated any need for &lt;em&gt;planning&lt;/em&gt; a conversation, which contributes to that activation energy requirement.&lt;/p&gt;
&lt;p&gt;However, it was like drinking from a firehose.&lt;/p&gt;
&lt;p&gt;I already knew that there was 
&lt;a href=&#34;https://youtu.be/lWNhg9qyTlQ?t=93&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;more to see than can ever be seen&lt;/a&gt;, but this experience lead me to reckon with that fact in a more tangible way.&lt;/p&gt;
&lt;p&gt;I installed 
&lt;a href=&#34;https://getferdi.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ferdi&lt;/a&gt;, and loaded up all the old Slacks I&amp;rsquo;d ever been added to. I was able to log into both my Discord accounts simultaneously, and also discovered that there are &lt;em&gt;public&lt;/em&gt; Discords about all sorts of things. Discourses too. And 
&lt;a href=&#34;https://nano.page&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;nano.page&lt;/a&gt;. Managed to mostly avoid Reddit. Signed into Gitter, which I previously rarely checked (so if you want to chat about Python Fire, join me 
&lt;a href=&#34;https://gitter.im/google/python-fire&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;there&lt;/a&gt;!) On top of those, and all the messaging apps I was already using before, I also fell into reading 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-10-01-infinite-distractions-and-getting-a-good-sear/&#34;&gt;my six infinite distractions&lt;/a&gt; more often. There were now more channels of information coming in than I could simultaneously keep in my head. My computer and I both ran out of RAM. Needed a reboot and a new strategy for dealing with these channels.&lt;/p&gt;
&lt;p&gt;The computer RAM issue turned out to be easier than the personal RAM one. Ferdi supports &amp;ldquo;hibernating&amp;rdquo; chat services when they&amp;rsquo;re not in use. My computer can now keep up with the chatter; I still can&amp;rsquo;t. 🤷‍♂️&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Limitations of Democratic Delegation-optional Voting</title>
      <link>https://davidbieber.com/snippets/2021-01-12-limitations-of-democratic-delegation-optional-voting/</link>
      <pubDate>Tue, 12 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-12-limitations-of-democratic-delegation-optional-voting/</guid>
      
      <description>&lt;p&gt;In 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-01-11-democratic-delegation-optional-voting/&#34;&gt;yesterday&amp;rsquo;s snippet&lt;/a&gt; I introduced the idea of &lt;em&gt;democratic delegation-optional voting&lt;/em&gt;. If you haven&amp;rsquo;t yet, read that first. Today, we&amp;rsquo;re going to be looking at its strengths and limitations.&lt;/p&gt;
&lt;h2 id=&#34;strengths&#34;&gt;Strengths&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;People can choose which issues matter most to them.&lt;/strong&gt; If an issue matters to you, you can vote on it directly. And so can all the people you convince to support your cause. You can do this even if your representatives disagree with you.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Representatives don&amp;rsquo;t need to be experts on everything.&lt;/strong&gt; If an issue is highly technical, representatives can delegate their constituents&#39; votes to someone who is a subject matter expert with similar values to the representative. If a voter doesn&amp;rsquo;t like the choice, they can make a different choice.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Residents don&amp;rsquo;t need to be experts on everything.&lt;/strong&gt; For most issues, most voters will delegate their votes to a Delegate. Residents can choose how much or how little time they want to spend researching individual issues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Residents don&amp;rsquo;t need to trust their representatives for multiple years.&lt;/strong&gt; If a resident disagrees with their representative on even a single issue, they can make their vote and their voice count for that issue. They&amp;rsquo;re not stuck with a representative that only half represents them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Power propagates to those who are trusted.&lt;/strong&gt; If people don&amp;rsquo;t like the way you&amp;rsquo;re voting, they can delegate their votes elsewhere. So, in order for a Delegate to keep their power, they need to keep the trust of their constituents.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The system can be implemented incrementally, even for as little as a single issue.&lt;/strong&gt; It can be implemented incrementally on top of existing forms of governance such as the US government. Democratic Delegation-optional Voting doesn&amp;rsquo;t require explicit elected representatives for matters that require voting (elected representatives have other important responsibilities, so they aren&amp;rsquo;t going away entirely with this system!)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DDoV can be used whenever the population of voters is well defined.&lt;/strong&gt; This makes it well suited both for running states and country legislatures, and for running school government or Prom Royalty elections.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The system is compatible with many existing forms of voting.&lt;/strong&gt; It works well with winner-take-all voting, ranked choice voting, approval voting, and proportional representation systems, for example.&lt;/p&gt;
&lt;h2 id=&#34;limitations&#34;&gt;Limitations&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;DDoV requires a mechanism for Delegate&amp;rsquo;s votes to be made public.&lt;/strong&gt; This isn&amp;rsquo;t so hard to do, but it does need to be done in a timely manner in order to give people the opportunity to change their vote in the 48 hour period following the election deadline.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A poor implementation could be prone to abuse of power by small Delegates.&lt;/strong&gt; How could this happen? If Delegates know how many ballots have been delegated to them, then a small Delegate could figure out whether or not a particular individual has delegated their votes to them. Of course, pressuring someone to delegate their vote to you is against the rules, but in many cases this would be hard to detect or enforce. To avoid this issue, a signature requirement (e.g. of 10 signatures from supporters who would use you as a default Delegate) could be required to become a Delegate. Once there&amp;rsquo;s this modest amount of public support for someone to become a Delegate, it shouldn&amp;rsquo;t be possible for a Delegate to determine if an individual is delegating votes to them or not. Alternatively, information about how many ballots each Delegate has delegated to them could be only provided in an approximate form.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reduces the capacity for backroom deals and compromises.&lt;/strong&gt; Okay, so this might actually be a strength. Since power is more in the hands of the people, it becomes far more difficult for one party to exchange favors with another (&amp;ldquo;if you support xyz in bill A, I&amp;rsquo;ll support qrs in bill B.&amp;quot;) I think this strength and/or limitation requires further study.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Democratic Delegation-optional Voting</title>
      <link>https://davidbieber.com/snippets/2021-01-11-democratic-delegation-optional-voting/</link>
      <pubDate>Mon, 11 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-11-democratic-delegation-optional-voting/</guid>
      
      <description>&lt;p&gt;In this snippet I propose a novel voting system, which I call &amp;ldquo;Democratic Delegation-optional Voting&amp;rdquo;. The core idea of the voting system is that anyone can choose to delegate their vote to a group or individual that they trust. They may change their delegate selection at any time and for any reason (including for a brief period after votes are cast, as we will see), or they may choose to cast a vote themselves rather than delegating their vote.&lt;/p&gt;
&lt;h2 id=&#34;what-problem-does-this-voting-system-solve&#34;&gt;What problem does this voting system solve?&lt;/h2&gt;
&lt;p&gt;Individual voters don&amp;rsquo;t have enough time or energy to research every issue up for vote. So, delegation is crucial. At the same time, voters shouldn&amp;rsquo;t yield their power to delegates entirely. If a voter feels passionately about an issue, they should not have to hope their representative&amp;rsquo;s views align with theirs.&lt;/p&gt;
&lt;h2 id=&#34;how-does-the-system-work&#34;&gt;How does the system work?&lt;/h2&gt;
&lt;p&gt;Ahead of a Vote, an individual or organization can register themselves as a Delegate. They need only do this once even if there will be many Votes.&lt;/p&gt;
&lt;p&gt;On its own, a Delegate has no voting power. Each voter gets one ballot. Each voter may choose to cast that ballot themselves, or they may delegate their ballot to a Delegate.&lt;/p&gt;
&lt;p&gt;Similarly, a Delegate may choose to cast its ballots itself, or it may choose to delegate them to another Delegate. If ten people have delegated their ballots to a Delegate, then it has ten times the voting power of an individual. A Delegate&amp;rsquo;s votes or delegation selections are public, whereas an individual&amp;rsquo;s votes or delegation selections are private.&lt;/p&gt;
&lt;p&gt;Votes may be cast or a Delegate selected at any time leading up to a Vote deadline. Votes may be modified and Delegate selections may be changed up until this deadline.&lt;/p&gt;
&lt;p&gt;Once the Vote deadline arrives, votes and delegation-selections made by Delegates are made public. Delegates can no longer change their selections at this point. Individual voters then have an additional 48 hours following the Vote deadline during which they may choose to modify their ballot.&lt;/p&gt;
&lt;p&gt;The system is flexible, in that it is compatible with winner-take-all voting, ranked choice voting, approval voting, proportional representation, etc.&lt;/p&gt;
&lt;h2 id=&#34;toy-example-playground-election&#34;&gt;Toy Example: Playground Election&lt;/h2&gt;
&lt;p&gt;We now demonstrate the voting system in a playground setting.&lt;/p&gt;
&lt;p&gt;Aaron, Brianna, Chloe, Daniel, and Emily are playing on the playground. Aaron and Brianna both want to use the swing. There&amp;rsquo;s only one swing. &amp;ldquo;Let&amp;rsquo;s vote!&amp;rdquo; suggests Emily. &amp;ldquo;Whoever gets more votes gets to swing.&amp;rdquo; Aaron and Brianna agree: whoever gets three or more votes wins. Daniel shrugs. &amp;ldquo;Chloe can have my vote!&amp;rdquo; he shouts, and he runs off to play alone on the seesaw.&lt;/p&gt;
&lt;p&gt;So Aaron, Brianna, Chloe and Emily each vote: Aaron and Brianna each for themselves, Chloe for Aaron and Emily for Brianna.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;So Aaron wins, 3-2, since Chloe&amp;rsquo;s vote also counts for Daniel!&amp;rdquo; Emily shouts. She&amp;rsquo;s really getting into this election thing.&lt;/p&gt;
&lt;p&gt;Just then Daniel comes tearing around the corner. &amp;ldquo;Wait! I thought you were going to vote for Brianna&amp;rdquo;, he tells Chloe. &amp;ldquo;Can I change my vote?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Emily, having studied &lt;em&gt;Democratic Delegation-optional Voting&lt;/em&gt; says &amp;ldquo;Sure, no trouble. Anyone else?&amp;rdquo; Hearing no other vote-changes, she proclaims Brianna the winner, and Aaron spends the rest of recess helping push Brianna higher on the swing.&lt;/p&gt;
&lt;h2 id=&#34;another-example-local-and-state-legislation&#34;&gt;Another Example: Local and State Legislation&lt;/h2&gt;
&lt;p&gt;For this example, consider a hypothetical local government and state government both using &lt;em&gt;Democratic Delegation-optional Voting&lt;/em&gt;. Over the next two weeks, the local government will be voting on two issues (the school budget and a commercial cannabis restriction ordinance), and the state government will also be voting on two issues (an unpopular jaywalking penalty and an obscure contract law thingy that affects very few people and is hard to understand).&lt;/p&gt;
&lt;p&gt;Many of the residents have set up simple &lt;em&gt;rules&lt;/em&gt; for choosing default Delegates. Several republican residents, they have selected their local republican Delegate as their default Delegate, and similarly several democratic residents have selected the local democratic Delegate as their default Delegate. Some residents have a rule-based system, where e.g. education-related issues are delegated to one Delegate while penal code issues are delegated to another.&lt;/p&gt;
&lt;p&gt;The Vote deadlines are set as follows, and the text of each issue is made available to the public two weeks prior to its Vote deadline:&lt;/p&gt;
&lt;p&gt;Local school budget: January 21, 2021&lt;/p&gt;
&lt;p&gt;State unpopular jaywalking penalty: January 22, 2021&lt;/p&gt;
&lt;p&gt;Local commercial cannabis restriction ordinance: January 28, 2021&lt;/p&gt;
&lt;p&gt;State obscure contract law thingy that affects very few people and is hard to understand: January 29, 2021&lt;/p&gt;
&lt;p&gt;Many of the residents hear about the unpopular jaywalking penalty, and they see how awful an idea it is, and so they directly submit a Nay vote on that issue. The penalty is overwhelmingly voted down.&lt;/p&gt;
&lt;p&gt;The school budget is a popular but particularly nuanced issue. While many residents chose to vote on it directly, we also see many residents choose a Delegate that they trust with school board issues, since they know this vote is important but complicated.&lt;/p&gt;
&lt;p&gt;For many people, the commercial cannabis restriction ordinance is an important issue too, but they trust their default Delegate will vote appropriately. The day after the election they&amp;rsquo;re surprised to read on their social media newsfeed of choice that one of the common default Delegates didn&amp;rsquo;t vote as expected, so they double check their vote. The vote looks fine. Clickbait post, I guess.&lt;/p&gt;
&lt;p&gt;Many of the residents don&amp;rsquo;t care about the obscure contract law thingy that affects very few people and is hard to understand, and so they leave their default Delegate selected. Some of the common default Delegates also don&amp;rsquo;t have time for obscure contract law, and so they choose to delegate their votes to still further, more specialized Delegates that they trust. (This is good because not only do most voters not have time to look into contract law, they also don&amp;rsquo;t have time to look into people who do have time to look into contract law, so they trust their Delegate to do &lt;em&gt;that&lt;/em&gt;.) Most of the voters are fine with how their vote ends up being cast, though a few don&amp;rsquo;t like the sub-Delegate their default-Delegate chose, and so those few can change their vote if they like.&lt;/p&gt;
&lt;p&gt;In all cases, the final votes are in and the election is tallied 48 hours after the election deadline. The school budget passes. The jaywalking penalty is voted down. The commercial cannabis restriction ordinance will go into effect immediately. And the obscure contract law thingy that affects very few people and is hard to understand&amp;hellip; well, to be honest I didn&amp;rsquo;t really follow that one too closely.&lt;/p&gt;
&lt;h2 id=&#34;some-observations&#34;&gt;Some observations&lt;/h2&gt;
&lt;p&gt;You&amp;rsquo;ve seen the &lt;em&gt;Democratic Delegation-optional Voting&lt;/em&gt; in action now. It&amp;rsquo;s &amp;ldquo;democratic&amp;rdquo;, because it gives everyone an equal voice in every election. Everyone gets precisely one vote. It&amp;rsquo;s &amp;ldquo;delegation-optional&amp;rdquo; because voters and Delegates alike have the choice of whether to vote directly, delegate their vote, or even skip voting altogether.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll notice that there are no explicit elected representatives in this system. There are merely different degrees of being an elected representative (the number of ballots you are responsible for as a Delegate). Anyone can register as a Delegate, and whether you make this a full-time job, investigating every single issue on the table, or whether you often delegate your votes further is up to you as a Delegate. Under this system, some common Delegates will be responsible for casting huge numbers of votes, while other Delegates will be responsible for casting just a handful.&lt;/p&gt;
&lt;p&gt;I mentioned that either an individual or an organization can register as a Delegate. If an organization registers as a Delegate they can select their votes through whatever process they choose (e.g. an internal election is fair game), and they are held to the same deadlines as every other Delegate.&lt;/p&gt;
&lt;h2 id=&#34;some-edge-cases-and-minor-details&#34;&gt;Some edge-cases and minor details&lt;/h2&gt;
&lt;p&gt;As mentioned in the Local and State Legislation example, a voter can set up simple rules for selecting their default Delegate. The voting system can also be extended to allow a voter to additionally specify &amp;ldquo;fall-through&amp;rdquo; backup Delegates. A ballot is given to a fall-through Delegate in the case that a voter&amp;rsquo;s higher-priority Delegate does not take an action on a particular piece of legislation.&lt;/p&gt;
&lt;p&gt;What happens if a major Delegate delegates their ballots to a trusted specialized delegate, but isn&amp;rsquo;t happy with how that trusted specialized delegate votes? They can contact their constituents and let them know. The constituents will have 48 hours during which they can change their vote.&lt;/p&gt;
&lt;p&gt;What happens if a Delegate A delegates their ballots to Delegate B, and Delegate B delegates their ballots to Delegate A? This should be easy to avoid in practice, because I expect Delegates will naturally have clear roles / specializations. Should it occur, however, no vote will be cast for voters delegating their ballot to those Delegates (unless a voter listed a backup Delegate), and the voters will have the usual 48 hours during which to place their vote.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Democratic Delegation-optional Voting&lt;/em&gt; truly puts governance in the hands of the people, without needing everyone to be an expert on everything. It makes Delegates accountable to their constituents, because a constituent can change their Delegates at any time. It allows people to perform their civic duty to precisely the extent that is appropriate for them. On the issues that matter most to them, they can cast an explicit vote. For the majority of issues, though, individuals don&amp;rsquo;t need to learn the details of every piece of legislation. They have the option to trust those to their Delegates.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A filesystem for social media</title>
      <link>https://davidbieber.com/snippets/2021-01-10-a-filesystem-for-social-media/</link>
      <pubDate>Sun, 10 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-10-a-filesystem-for-social-media/</guid>
      
      <description>&lt;p&gt;
&lt;a href=&#34;https://omar.website/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Omar Riswan&lt;/a&gt; has an excellent project called 
&lt;a href=&#34;https://omar.website/tabfs/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;TabFS&lt;/a&gt; that takes your browser tabs and exposes them to you as a filesystem. When you run &lt;code&gt;ls&lt;/code&gt;, you see a list of all your open tabs. &lt;code&gt;rm&lt;/code&gt; on a tab directory closes the tab. Inspecting the tab with standard tools (&lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;rm&lt;/code&gt;, etc) allow you to do things like reading the title or contents of the tab (yes, the whole tab&amp;rsquo;s contents!), closing the tab, or running javascript in the tab. The whole thing is quite clever.&lt;/p&gt;
&lt;p&gt;Inspired by TabFS, I envision another non-conventional filesystem: Social Media FS.&lt;/p&gt;
&lt;p&gt;First you mount smfs and authenticate with your social media providers. Then if you &lt;code&gt;ls&lt;/code&gt; the mounted directory, you can see each of the places you can read from and write to on social media.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a directory full of your chat threads. The timestamps indicate when they were created and when they were most recently modified. You can read the contents of the chat, or send a new message just as easily (and via the same tools) as you would write a file to disk.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a directory of all the Facebook posts made by all your friends and all the groups you follow. Each post has a file with its contents, and also one with all the comments and reactions to it. You can make a new post or add a new comment the same way you&amp;rsquo;d make a new file.&lt;/p&gt;
&lt;p&gt;You can use standard tools for monitoring for new content. I like to use 
&lt;a href=&#34;https://pythonhosted.org/watchdog/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Python&amp;rsquo;s watchdog&lt;/a&gt; for this.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a directory for ads too, which you&amp;rsquo;re welcome to peruse or delete as you see fit.&lt;/p&gt;
&lt;p&gt;Reacting to a twitter post, sending a DM, receiving discord or slack or signal messages&amp;hellip; all of these are organized as files and folders, and actions can be performed simply through file reads and writes.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d sure love to use a filesystem like this, and 
&lt;a href=&#34;https://davidbieber.com/projects/bieber-bot/&#34;&gt;Bieber Bot&lt;/a&gt; would too.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Mobile Distraction Detection, at last</title>
      <link>https://davidbieber.com/snippets/2021-01-09-mobile-distraction-detection-at-last/</link>
      <pubDate>Sat, 09 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-09-mobile-distraction-detection-at-last/</guid>
      
      <description>&lt;p&gt;I have implemented a minimal working version of mobile &lt;em&gt;distraction detection&lt;/em&gt;, complete with a simple intervention for when I visit distracting websites on my phone.&lt;/p&gt;
&lt;h2 id=&#34;what-does-distraction-detection-do&#34;&gt;What does &amp;ldquo;distraction detection&amp;rdquo; do?&lt;/h2&gt;
&lt;p&gt;It runs on my laptop and monitors my &lt;em&gt;phone&lt;/em&gt; for when I visit distracting websites. I give it a list of distracting websites for it to keep an eye out for. My list is: twitter, facebook, hacker news, google news, reddit, and youtube.&lt;/p&gt;
&lt;p&gt;I can set it to perform some action whenever I&amp;rsquo;m on one of these websites. For this first iteration, I&amp;rsquo;m having Bieber Bot message me whenever it notices I&amp;rsquo;m on one of these websites. Now that it&amp;rsquo;s working though, it will be easy to customize to my liking.&lt;/p&gt;
&lt;p&gt;In future iterations, I&amp;rsquo;ll have it wait until I&amp;rsquo;ve been spending several minutes on the website before messaging me, and I&amp;rsquo;ll only have it do this during times when I mean to be focused.&lt;/p&gt;
&lt;h2 id=&#34;why-is-this-interesting&#34;&gt;Why is this interesting?&lt;/h2&gt;
&lt;p&gt;There are excellent browser extensions that help you take control of your browsing habits on your computer. I recommend DK&amp;rsquo;s 
&lt;a href=&#34;https://getintention.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Intention&lt;/a&gt; for this. However, there aren&amp;rsquo;t great solutions like Intention for mobile browsing.&lt;/p&gt;
&lt;p&gt;The challenge is that mobile browsers don&amp;rsquo;t provide good ways for developers to write extensions. I&amp;rsquo;ve built my mobile distraction detector in spite of this limitation :).&lt;/p&gt;
&lt;h2 id=&#34;how-does-it-work&#34;&gt;How does it work?&lt;/h2&gt;
&lt;p&gt;I use an iPhone and the Chrome browser. I&amp;rsquo;m logged into my Google Account on Chrome on both my phone and my laptop, and I have tab syncing turned on. With tab syncing, all my tab sessions from my phone are synced to my Google account, and are visible on my laptop, usually with a sub-minute latency. You can view this data in human-readable form at 
&lt;a href=&#34;chrome://history/syncedTabs&#34;&gt;chrome://history/syncedTabs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The tab session data is stored along with the rest of my Chrome data. Since I use a Mac, the path is &lt;code&gt;~/Library/Application\ Support/Google/Chrome/Profile\ 1/Sync\ Data/LevelDB/&lt;/code&gt;. Note that &amp;ldquo;Profile 1&amp;rdquo; may be replaced with either &amp;ldquo;Default&amp;rdquo;, or the name of your Profile, depending on how many Google accounts you have connected with Chrome.&lt;/p&gt;
&lt;p&gt;The data is stored in a LevelDB database (this is unusual for Chrome; most of the rest of your Chrome data is stored in sqlite3 databases). LevelDB is an efficient key-value store, which was written by Jeff Dean and Sanjay Ghemawat back in 2011. The keys which contain the synced tab data are those prefixed with &amp;ldquo;session-dt&amp;rdquo;. The corresponding values are &lt;code&gt;SessionSpecifics&lt;/code&gt; protocol buffers. 
&lt;a href=&#34;https://source.chromium.org/chromium/chromium/src/&amp;#43;/master:components/sync/protocol/session_specifics.proto&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;The protocol buffer definition is available here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Before parsing the sync data, I always make a copy of it first, and then I only ever open the copy. This ensures that Chrome doesn&amp;rsquo;t have a lock on the database, and isn&amp;rsquo;t editing it concurrently with my own program reading it.&lt;/p&gt;
&lt;p&gt;I use the Python library &lt;code&gt;plyvel&lt;/code&gt; to parse the LevelDB database: &lt;code&gt;db = plyvel.DB(path_to_copy_of_leveldb_directory)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In order to use the protobuf definition, I compiled it first with protoc: &lt;code&gt;protoc -I chromium/ chromium/components/sync/protocol/*.proto --python_out=dbieber/distraction_detection/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Putting these pieces together, accessing the session data looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import plyvel
from components.sync.protocol import session_specifics_pb2

db = plyvel.DB(path)

for key, value in db.iterator():
  if b&#39;sessions-dt&#39; in key:
	session = session_specifics_pb2.SessionSpecifics.FromString(value)

db.close()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From here, the key remaining piece to understand is how to figure out which tabs are open on which devices.&lt;/p&gt;
&lt;p&gt;Each of the SessionSpecifics protos has an attribute: &lt;code&gt;session_tag&lt;/code&gt; which uniquely identifies a session. For each &lt;code&gt;session_tag&lt;/code&gt;, there is a single SessionSpecifics proto with a &lt;code&gt;client_name&lt;/code&gt; attribute: this indicates which device the session lives on. Each of the remaining SessionSpecifics protos with that same tag correspond to a single tab, and the currently open URL for that tab comes from &lt;code&gt;session.tab.navigation[-1].virtual_url&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;From there, it&amp;rsquo;s just a matter of matching the URLs against my list of distracting websites, and sending the data off to Bieber Bot. Distractions, detected. :D&lt;/p&gt;
&lt;h2 id=&#34;what-next&#34;&gt;What next?&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ll tweak my own distraction detection setup to something that makes sense for me. Instead of immediate messages from Bieber Bot, I&amp;rsquo;ll have him try to keep my total senseless scrolling for a day to a moderate amount. I&amp;rsquo;ll have him be particularly vigilant about helping me keep my morning scrolling from going on too long.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll also send this snippet around to folks interested in building similar tools. While I won&amp;rsquo;t be turning this into a product for the masses, I&amp;rsquo;m hopeful that the method does get picked up by projects like Intention, ActivityWatch, and other tools that aim to help people maintain healthy browsing habits.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t think it&amp;rsquo;s common knowledge that with account syncing, rich data about your mobile browsing is available on your computer. So today, there isn&amp;rsquo;t much tooling that takes advantage of this. If you work on a product in this space, well, now you&amp;rsquo;ve had a glimpse of what data&amp;rsquo;s available and what it can do. Consider using this approach to extend the reach of your product.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Will it be harder to write snippets now?</title>
      <link>https://davidbieber.com/snippets/2021-01-09-will-it-be-harder-to-write-snippets-now/</link>
      <pubDate>Sat, 09 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-09-will-it-be-harder-to-write-snippets-now/</guid>
      
      <description>&lt;p&gt;Now that I&amp;rsquo;ve 
&lt;a href=&#34;https://davidbieber.com/post/2021-01-08-where-are-all-the-posts-from-2020/&#34;&gt;linked to the snippets section from my main website&lt;/a&gt;, will it be harder to write snippets? I hope not. I&amp;rsquo;ll have to make an even more concerted effort to lower the quality bar though.&lt;/p&gt;
&lt;p&gt;The goal, as always, is for the snippets section to avoid any inhibitions. Writing here should be as easy as thinking aloud. A tiny post like this ought to help in this regard.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Distraction detection: Proto acquired!</title>
      <link>https://davidbieber.com/snippets/2021-01-08-distraction-detection-proto-acquired/</link>
      <pubDate>Fri, 08 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-08-distraction-detection-proto-acquired/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;m &lt;strong&gt;inching&lt;/strong&gt; my way toward writing a distraction detector that will allow Bieber Bot to notice when I&amp;rsquo;m distracted on my phone and stage an intervention. (Wow!, I first pitched this idea (to myself) 
&lt;a href=&#34;https://davidbieber.com/snippets/2019-12-30-analyzing-my-browser-history/&#34;&gt;in one of my very first snippets&lt;/a&gt;, back in 2019.)&lt;/p&gt;
&lt;p&gt;Most recently 
&lt;a href=&#34;https://davidbieber.com/snippets/2021-01-01-programmatically-accessing-chromes-tabs-from-other-devices-data/&#34;&gt;I figured out where Chrome&amp;rsquo;s &amp;ldquo;Tabs from other devices&amp;rdquo; data is stored&lt;/a&gt;. However, I couldn&amp;rsquo;t parse the data because I didn&amp;rsquo;t know what the protocol buffer definition being used was.&lt;/p&gt;
&lt;p&gt;Today, I heard back from someone who works on Chrome. I&amp;rsquo;ve acquired the proto definitions!&lt;/p&gt;
&lt;p&gt;The 
&lt;a href=&#34;https://source.chromium.org/chromium/chromium/src/&amp;#43;/master:components/sync/protocol/session_specifics.proto&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;proto definitions are here&lt;/a&gt; and 
&lt;a href=&#34;https://source.chromium.org/chromium/chromium/src/&amp;#43;/master:components/sync_sessions/session_store.cc&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;the code that persists the data to disk is here&lt;/a&gt;. I can successfully bulid the protos (using protoc) and I can parse my session data from the leveldb database. Progress!&lt;/p&gt;
&lt;p&gt;The trouble now is my phone seems to have stopped syncing its tabs two days ago. Weird! One more mystery to solve I guess&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A social network for slow long-form discussions</title>
      <link>https://davidbieber.com/snippets/2021-01-07-a-social-network-for-slow-long-form-discussions/</link>
      <pubDate>Thu, 07 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-07-a-social-network-for-slow-long-form-discussions/</guid>
      
      <description>&lt;p&gt;A social network&amp;rsquo;s design influences the conversations that people will have on it. Can we design a social network that will facilitate healthy debate and discussion, while avoiding toxic discourse?&lt;/p&gt;
&lt;p&gt;Consider this: a variant of Twitter where instead of a 140 character maximum, there&amp;rsquo;s a 1400 word maximum. (We could also impose a 140 character minimum?) And you&amp;rsquo;re limited to just 3 posts per day.&lt;/p&gt;
&lt;p&gt;The real twist though? All posts are posted at the same time: at 8am, 2pm, 8pm, and 2am. We choose times scatter across the day so your timezone doesn&amp;rsquo;t matter.&lt;/p&gt;
&lt;p&gt;Actually, scrap the reference to Twitter altogether. The feel I&amp;rsquo;m going for is discussion focused, not shouting-into-the-void focused. So, think Reddit with all these weird limitations tacked on.&lt;/p&gt;
&lt;p&gt;The hope is that having infrequent postings gives people a chance to breathe: no one&amp;rsquo;s expecting a response in seconds or minutes. The hope is that this also gives people a chance to think; this can be a place where long-form well thought out discussion takes place. And the hope is also this rate-limited schedule eliminates any of the infinite-scroll / endless-refreshing that comes with existing popular social media.&lt;/p&gt;
&lt;p&gt;Think it could work? I think it could.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Brains Don&#39;t Do Solomonoff Induction</title>
      <link>https://davidbieber.com/snippets/2021-01-06-brains-dont-do-solomonoff-induction/</link>
      <pubDate>Wed, 06 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-06-brains-dont-do-solomonoff-induction/</guid>
      
      <description>&lt;p&gt;
&lt;a href=&#34;http://zhat.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dan Abolafia&lt;/a&gt; asked me some thought provoking questions about Solomonoff Induction and intelligence. This snippet comes from my answers.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Question: Do you think a person has a hypothesis space and prior that are fixed at the moment of birth and never change over the course of the person&amp;rsquo;s life?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;tl;dr Nope.&lt;/p&gt;
&lt;p&gt;There are different levels at which you can define hypothesis space. Consider two statements.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Statement [1]: People learn and change their prior over hypotheses based on their observations and experiences over time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In statement [1] (which I hope is unobjectionably true), &amp;ldquo;hypotheses&amp;rdquo; refers to hypotheses that will be formed during a person&amp;rsquo;s life.&lt;/p&gt;
&lt;p&gt;A person&amp;rsquo;s belief about their hypotheses can change in response to new information. This can be done in a Bayesian way, using as a prior at any particular moment their beliefs from before gaining that new information. When they gain new information, they apply Bayesian inference to compute the posterior. The posterior becomes the new prior for the next time new information is obtained.&lt;/p&gt;
&lt;p&gt;You can also &amp;ldquo;refactor&amp;rdquo; statement [1] to instead read:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Statement [2]: The &amp;lsquo;computation that a person embodies&amp;rsquo; is fixed at birth.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;[1] and [2] are completely consistent with one another.&lt;/p&gt;
&lt;p&gt;(Let me know if the term &amp;lsquo;computation that a person embodies&amp;rsquo; needs clarifying.)&lt;/p&gt;
&lt;p&gt;From the perspective of [2], a person has a single prior over &amp;ldquo;hypotheses&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;(Or more precisely: a person has a single &amp;ldquo;hypothesis&amp;rdquo;, which came from a single prior. But the person didn&amp;rsquo;t &amp;lsquo;have&amp;rsquo; that prior; instead, the process by which they were created did.)&lt;/p&gt;
&lt;p&gt;Here a &amp;ldquo;hypothesis&amp;rdquo; is a much larger thing than in [1]. It&amp;rsquo;s the complete manner in which the person will determine how to respond to inputs over the course of their life. (That is, it&amp;rsquo;s the &amp;lsquo;computation that the person embodies&amp;rsquo;.)&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s an interesting question to ask whether these hypotheses come from something that approximates Solomonoff induction.&lt;/p&gt;
&lt;p&gt;Note that this wouldn&amp;rsquo;t be the &amp;ldquo;brain approximating Solomonoff induction&amp;rdquo; original question &amp;ndash; rather, it would be more like &amp;ldquo;evolution approximating Solomonoff induction&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;[Aside: And to answer this question: I don&amp;rsquo;t think single reward minimization is the most natural way to model what these complex physical processes are doing; there are lots of competing forces at play. So even though you could in principle distill them to a single reward function, I don&amp;rsquo;t think that&amp;rsquo;s the most useful way of modeling things of this complexity and scale. Update: now that I have a better understanding of Solomonoff induction, I see how this doesn&amp;rsquo;t answer the question.]&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If the answer to the main question is No, there needs to be an extra-Bayesian method for choosing priors and hypothesis spaces.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I agree with this.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s return to perspective [1]. At any given time, a person might have some beliefs about the world. Then they acquire new information. They update their beliefs. This in principle can be done in a Bayesian way all throughout ones life.&lt;/p&gt;
&lt;p&gt;In practice, there need to be other processes at work, because people develop new concepts, choose to think about some things more than others, forget stuff, etc.&lt;/p&gt;
&lt;p&gt;But with infinite memory and infinitely fast compute, an agent could in principle start with all possible concepts, and just keep doing Bayesian updates throughout their life, and I think such an agent would do quite well for themselves.&lt;/p&gt;
&lt;p&gt;Note: for a hypothetical agent like this, the answer to the original question would be Yes. But agents like this don&amp;rsquo;t exist.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Agree or disagree: The brain samples hypotheses from a universal unchanging prior.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This I disagree with. I hope perspective [1] clarifies why.&lt;/p&gt;
&lt;p&gt;Any action that the brain takes, such as sampling a hypothesis, is happening during an individual&amp;rsquo;s life. Of course it&amp;rsquo;s going to take into account all the experiences of the individual.&lt;/p&gt;
&lt;p&gt;You could of course mean &amp;ldquo;hypothesis&amp;rdquo; in the sense of [2], where the complete life experiences of the individual are inputs to the hypothesis. But then why wait until there&amp;rsquo;s a brain at all to sample the hypothesis? Now we&amp;rsquo;re talking about a hypothesis (the &amp;lsquo;computation that the person embodies&amp;rsquo;) that has been in existence at least since the person&amp;rsquo;s birth.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Do you think [1] and [2] are equivalent?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think they are two ways of describing the same situation. So, in that sense, yes.&lt;/p&gt;
&lt;p&gt;I could see why people might disagree with this though. People can make good arguments that you&amp;rsquo;re not just a fixed embodied computation. I think these arguments are wrong, but people can still make them. These hypothetical people would regard [1] as correct and [2] as incorrect, whereas I think both [1] and [2] are correct.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Bayesian inference doesn&amp;rsquo;t provide a way to create or destroy hypotheses. It merely provides a way for updating one&amp;rsquo;s beliefs about existing hypotheses. How do you reconcile this with [1] and [2]?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is right. Hypotheses can&amp;rsquo;t be &amp;ldquo;formed&amp;rdquo; from Bayesian inference. As I was describing perspective [1], I was envisioning hypotheses being formed in some (likely extra-Bayesian, but it wasn&amp;rsquo;t important) way and merely being updated via Bayesian inference.&lt;/p&gt;
&lt;p&gt;[Aside: How are these hypotheses formed though?&lt;/p&gt;
&lt;p&gt;Well, if you already have a prior for the state of the universe, then you might (1) make a determination about what variables are relevant to the situation, and (2) marginalize out all other variables. No need to do this though if memory and compute aren&amp;rsquo;t limited.]&lt;/p&gt;
&lt;p&gt;Earlier I wrote:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Let&amp;rsquo;s return to perspective [1]. At any given time, a person might have some beliefs about the world. Then they acquire new information. They update their beliefs. This in principle can be done in a Bayesian way all throughout ones life.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;How does this work, you ask?&lt;/p&gt;
&lt;p&gt;It relies on the agent starting with a prior over all possible hypotheses. This avoids the issue of needing to create hypotheses along the way, which Bayesian inference doesn&amp;rsquo;t provide a mechanism for.&lt;/p&gt;
&lt;p&gt;I tried to describe this by the following text:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;With infinite memory and infinitely fast compute, an agent could in principle start with all possible concepts, and just keep doing Bayesian updates throughout their life, and I think such an agent would do quite well for themselves.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If I understand correctly, this &lt;strong&gt;is&lt;/strong&gt; (more or less) Solomonoff induction. (I didn&amp;rsquo;t realize this at the start of the conversation.)&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve started with a universal prior and applied bayesian inference to update it as we made observations.&lt;/p&gt;
&lt;p&gt;Of course, this isn&amp;rsquo;t what people do. So, my answer to the overall initial question is just a simple &amp;ldquo;Nope.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>ffmpeg aspirations</title>
      <link>https://davidbieber.com/snippets/2021-01-05-ffmpeg-aspirations/</link>
      <pubDate>Tue, 05 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-05-ffmpeg-aspirations/</guid>
      
      <description>&lt;ul&gt;
&lt;li&gt;turn a collection of photos into a slide show&lt;/li&gt;
&lt;li&gt;set it to music&lt;/li&gt;
&lt;li&gt;add gentle transitions, like a slow pan of the camera&lt;/li&gt;
&lt;li&gt;fade the music in and out to change songs&lt;/li&gt;
&lt;li&gt;given a file of time stamp ranges, clip to just those parts of the file&lt;/li&gt;
&lt;li&gt;given a file of timestamp ranges, each with a speed multiplier, adjust the speed of each clip and stitch together the clips&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have code that does this last one already, but I suspect it can be orders of magnitude faster done as an ffmpeg command compared with the way I&amp;rsquo;m doing it now.&lt;/p&gt;
&lt;h2 id=&#34;turn-a-collection-of-photos-into-a-slide-show&#34;&gt;Turn a collection of photos into a slide show:&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;ffmpeg \
  -r 1/5 \
  -pattern_type glob -i &amp;quot;/Users/dbieber/Documents/video/raw/*.png&amp;quot; \
  -c:v libx264 \
  -r 30 \
  -pix_fmt yuv420p \
  output.mp4
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next up, I&amp;rsquo;ll see if I can add some audio, and I&amp;rsquo;ll work my way down the list.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>More Datalog Queries for Roam</title>
      <link>https://davidbieber.com/snippets/2021-01-04-more-datalog-queries-for-roam/</link>
      <pubDate>Mon, 04 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-04-more-datalog-queries-for-roam/</guid>
      
      <description>&lt;p&gt;In this snippet I share datalog queries for Roam Research. For more such queries (and to see how to run these queries), 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-12-22-datalog-queries-for-roam-research/&#34;&gt;see this earlier snippet on the subject&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pages-tagged-with-x-not-listed-on-page-y&#34;&gt;Pages tagged with &amp;ldquo;X&amp;rdquo; not listed on page &amp;ldquo;Y&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;This query is useful when constructing an index page. Let&amp;rsquo;s say you want to take all the pages you&amp;rsquo;ve tagged with &amp;ldquo;[[Brilliant Idea]]&amp;rdquo; and organize them on a page called &amp;ldquo;[[Brilliant Ideas Index]]&amp;rdquo;. This query will find you all the pages that are tagged with &amp;ldquo;[[Brilliant Idea]]&amp;rdquo; that haven&amp;rsquo;t yet been added to the &amp;ldquo;[[Brilliant Ideas Index]]&amp;rdquo; page.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;let container = &amp;quot;Brilliant Ideas Index&amp;quot;;
let tag = &amp;quot;Brilliant&amp;quot;;
let ancestor = `[ 
  [(ancestor ?child ?parent)
   [?parent :block/children ?child]]
  [(ancestor ?child ?ancestor)
   [?parent :block/children ?child]
   (ancestor ?parent ?ancestor)]
]`;

var blocks = window.roamAlphaAPI.q(`
[:find ?page_title
  :in $ % ?container_title ?tag_text
  :where 
    [?container_page :node/title ?container_title]
    [?page :node/title ?page_title]
    (ancestor ?tagged_block ?page)
    [?tagged_block :block/refs ?tag_page]
    [?tag_page :node/title ?tag_text]
    (not (ancestor ?container_block ?container_page)
         [?container_block :block/refs ?page])
]`, ancestor, container, tag)

console.log(blocks.map((data, index) =&amp;gt; {return `[[${data[0]}]]`}).join(&#39;\n&#39;));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hope this is useful for getting your Roam graph organized!&lt;/p&gt;
&lt;h2 id=&#34;blocks-tagged-with-both-x-and-y&#34;&gt;Blocks tagged with both &amp;ldquo;X&amp;rdquo; and &amp;ldquo;Y&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;I use a query like this to find blocks tagged with both &amp;ldquo;Snippets&amp;rdquo; and &amp;ldquo;ok-to-publish&amp;rdquo;, in order to automatically publish snippets to my website.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;let tag1 = &amp;quot;Snippets&amp;quot;;
let tag2 = &amp;quot;ok-to-publish&amp;quot;;
var blocks = window.roamAlphaAPI.q(`[
	:find ?uid ?string
	:in $ ?tag1 ?tag2
	:where
	[?block :block/uid ?uid]
	[?block :block/string ?string]
	[?block :block/refs ?block_tag1]
	[?block :block/refs ?block_tag2]
	[?block_tag1 :node/title ?tag1]
	[?block_tag2 :node/title ?tag2]
]`, tag1, tag2);

blocks.map(
  (data, index) =&amp;gt; {return `((${data[0]})): ${data[1]}`;})
.join(&#39;\n&#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;info-about-all-children-of-any-block-tagged-with-both-x-and-y&#34;&gt;Info about all children of any block tagged with both &amp;ldquo;X&amp;rdquo; and &amp;ldquo;Y&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;This extends the previous query in two key ways: (1) it gets all children of any block with both tags, and (2) it gets more detailed information about those children. The ?uid indicates which block has the two target tags, while the ?child_uid, ?parent_uid, and ?order fields allow for reconstructing the arrangement of the child blocks. Each returned record has the text of a child block, it&amp;rsquo;s uid (?child_uid), it&amp;rsquo;s parent&amp;rsquo;s uid (?parent_uid), and the order of that child in its parent&amp;rsquo;s list of children. Together, this information allows you to fully reconstruct the tree of blocks beneath each of the tagged blocks.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;let tag1 = &amp;quot;Snippets&amp;quot;;
let tag2 = &amp;quot;ok-to-publish&amp;quot;;
let ancestor = `[ 
  [(ancestor ?child ?parent)
   [?parent :block/children ?child]]
  [(ancestor ?child ?ancestor)
   [?parent :block/children ?child]
   (ancestor ?parent ?ancestor)]
]`;

let block_info = window.roamAlphaAPI.q(`[
  :find ?uid ?child_text ?child_uid ?parent_uid ?order
  :in $ % ?tag1 ?tag2
  :where
  [?block :block/uid ?uid]
  [?block :block/string ?string]
  [?block :block/refs ?block_tag1]
  [?block :block/refs ?block_tag2]
  [?block_tag1 :node/title ?tag1]
  [?block_tag2 :node/title ?tag2]
  (ancestor ?child ?block)
  [?parent :block/children ?child]
  [?parent :block/uid ?parent_uid]
  [?child :block/uid ?child_uid]
  [?child :block/order ?order]
  [?child :block/string ?child_text]
]`, ancestor, tag1, tag2);

block_info.map(
  (data, index) =&amp;gt; {return `((${data[0]})) ${data[1]}`;})
.join(&#39;\n&#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I use the following script to organize the blocks by their parent:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;class DefaultDict {
  constructor(defaultInit) {
    return new Proxy({}, {
      get: (target, name) =&amp;gt; name in target ?
        target[name] :
        (target[name] = typeof defaultInit === &#39;function&#39; ?
          new defaultInit().valueOf() :
          defaultInit)
    })
  }
}

var blocks_by_parent = new DefaultDict(Array);
block_info.forEach(
  (info) =&amp;gt; {
    [uid, child_text, child_uid, parent_uid, order] = info;
    blocks_by_parent[parent_uid].push(info);
  }
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then the following function &lt;code&gt;blocksInOrder&lt;/code&gt; to place the children in their proper order.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;function blocksInOrder(blocks_by_parent, uid) {
  var blocks = [];
  var blocks_list = blocks_by_parent[uid].sort(
    (b1, b2) =&amp;gt; {return b1[4] - b2[4];}
  );
  blocks_list.forEach((block) =&amp;gt; {
    blocks.push(block)
    blocks.push(...blocksInOrder(blocks_by_parent, block[2]));
  });
  return blocks;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a key component of how I do 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-12-28-publishing-blog-posts-from-roam-research-quickly-and-automatically/&#34;&gt;automatic snippet publishing from Roam to my website&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>2020 Resolution Check-in</title>
      <link>https://davidbieber.com/snippets/2021-01-03-2020-resolution-check-in/</link>
      <pubDate>Sun, 03 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-03-2020-resolution-check-in/</guid>
      
      <description>&lt;p&gt;At the start of 2020 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-01-01-new-years-resolutions/&#34;&gt;I resolved to communicate publicly 100 times&lt;/a&gt;. How did I do? I got about 80% of the way there.&lt;/p&gt;
&lt;p&gt;By the numbers, this is approximately 62 snippets, 8 tech talks, 4 published papers, 1 thesis proposal, 2 videos, and a handful of discussions in public on various Slack-like groups.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Resolution&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;Communicate publicly 100 times&lt;/td&gt;
&lt;td&gt;80%&amp;rsquo;s not bad.&lt;/td&gt;
&lt;td&gt;&lt;font color=&#34;maroon&#34;&gt;Not quite.&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;td&gt;Play violin on 100 days&lt;/td&gt;
&lt;td&gt;Played on 43 days&lt;/td&gt;
&lt;td&gt;&lt;font color=&#34;maroon&#34;&gt;Nope&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2017&lt;/td&gt;
&lt;td&gt;Longer arms&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;font color=&#34;green&#34;&gt;Yesssss!&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2015&lt;/td&gt;
&lt;td&gt;Exercise 200 days&lt;br&gt; Read 200 days&lt;/td&gt;
&lt;td&gt;Exercise: 200 days by summer&lt;br&gt; Reading: (look this up)&lt;/td&gt;
&lt;td&gt;Yes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2013&lt;/td&gt;
&lt;td&gt;100 days of push ups&lt;/td&gt;
&lt;td&gt;145 done by December&lt;/td&gt;
&lt;td&gt;&lt;font color=&#34;green&#34;&gt;Yes!&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Here&amp;rsquo;s to 2021 🥂&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Spaced Repetition in Roam Research</title>
      <link>https://davidbieber.com/snippets/2021-01-02-spaced-repetition-in-roam-research/</link>
      <pubDate>Sat, 02 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-02-spaced-repetition-in-roam-research/</guid>
      
      <description>&lt;p&gt;There are many ways to do spaced repetition in Roam Research. This post describes mine. I was inspired to start this two months ago by reading 
&lt;a href=&#34;https://ncase.me/remember/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Nicky Case&amp;rsquo;s comic on spaced repetition&lt;/a&gt;, and I highly recommend the read.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Spaced repetition&amp;rdquo; just means studying flashcards, studying the cards you know best less often, and study the cards you struggle with more often. It&amp;rsquo;s a powerful technique for learning and remembering material, whether you&amp;rsquo;re a student or a lifelong learner.&lt;/p&gt;
&lt;p&gt;The system I use is based on a classic system called the &amp;ldquo;Leitner Box&amp;rdquo; method. I&amp;rsquo;ll first describe how to use the &amp;ldquo;Leitner Box&amp;rdquo; approach in Roam, and then I&amp;rsquo;ll describe the adjustments I made to improve it.&lt;/p&gt;
&lt;h2 id=&#34;whats-a-leitner-box&#34;&gt;What&amp;rsquo;s a &amp;ldquo;Leitner Box&amp;rdquo;?&lt;/h2&gt;
&lt;p&gt;In the &amp;ldquo;Leitner Box&amp;rdquo; system of spaced repetition, there are seven boxes numbered Box 1 through Box 7. When you create a flashcard, you place it into Box 1. Every day, you use a schedule to determine which boxes of cards to review. The cards in box 1 get reviewed most often, and the cards in box 7 get reviewed least often. When you review a card, you move it up a box (e.g. from box 1 to 2 or from box 4 to 5) if you get the card right. But if you get a card wrong, you move the card back to box 1.&lt;/p&gt;
&lt;p&gt;The default Leitner Box schedule looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://firebasestorage.googleapis.com/v0/b/firescript-577a2.appspot.com/o/imgs%2Fapp%2Fplayground%2FpW7FsufOIr.png?alt=media&amp;amp;token=3cbd07b1-11e5-4389-896d-9a181f6529fc&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;How do you read this schedule?&lt;/p&gt;
&lt;p&gt;The colored circles represent the different Leitner Boxes. The red circles represent Box 1, the orange circles represent Box 2, the yellow circles represent Box 3, all the way up to the final pink circle that represents Box 7.&lt;/p&gt;
&lt;p&gt;The numbers along the bottom are &amp;ldquo;session numbers&amp;rdquo;. For your first review session, you look at the circles above &amp;ldquo;01&amp;rdquo; (Boxes 2 and 1). For your second review session, you look at the circles above &amp;ldquo;02&amp;rdquo; (Boxes 3 and 1). Always review boxes for a given day in order from highest to lowest. After completing session &amp;ldquo;64&amp;rdquo;, the schedule wraps around and your next session is session &amp;ldquo;01&amp;rdquo; again.&lt;/p&gt;
&lt;p&gt;To recap, (1) you put new flashcards into Box 1. (2) When you get a card correct, you move it up a box. (3) When you get a card incorrect, you move it all the way back to Box 1. (4) You use the schedule made of colored dots to decide which boxes to review each day, answering questions in higher boxes first.&lt;/p&gt;
&lt;h2 id=&#34;setting-up-leitner-boxes-in-roam&#34;&gt;Setting up Leitner Boxes in Roam&lt;/h2&gt;
&lt;p&gt;This system is all well and good. How do we put it into practice? Here I&amp;rsquo;ll quickly describe (1) getting set up, (2) creating new flashcards, and (3) how to do a review session.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setting up:&lt;/strong&gt; You can use my template; simply copy and paste the 
&lt;a href=&#34;https://pastebin.com/GPfhcUug&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&amp;ldquo;raw&amp;rdquo; text at the bottom of the page here&lt;/a&gt; into Roam Research, e.g. onto a new page named &amp;ldquo;Spaced Repetition&amp;rdquo;. For this to work you need to copy from the region that says &lt;strong&gt;&amp;ldquo;RAW paste data&amp;rdquo;&lt;/strong&gt;. You can 
&lt;a href=&#34;https://pastebin.com/zvjFKZAb&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;get the enhanced template (recommended; see below) here&lt;/a&gt;. Again, be sure to copy from the region that says &amp;ldquo;RAW paste data&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;The default template creates a page for each of the seven Leitner boxes. It also puts the default schedule on the page, and gives you a place to keep track of what session number you&amp;rsquo;re up to. It will also add two questions to your Leitner Box 1 (one about avocados, and one about Cloze deletions), and includes some basic instructions for how to do spaced repetition in Roam.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Creating New Flashcards:&lt;/strong&gt; You can create a new card anywhere in your Roam graph simply by tagging a note with &amp;ldquo;#[[Leitner Box 1]]&amp;rdquo;. Here are two ways to create cards in Roam:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Put the question on one bullet, and put the answer in the child bullets. Then tag the bullet with the question with &amp;ldquo;#[[Leitner Box 1]]&amp;rdquo; to add it to your spaced repetition system.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can use the syntax {{=: question | answer}} in Roam to create text that remains hidden until clicked. The text &amp;ldquo;answer&amp;rdquo; won&amp;rsquo;t appear until you click on the text &amp;ldquo;question.&amp;rdquo; Again, tag the line with &amp;ldquo;#[[Leitner Box 1]]&amp;rdquo; to add it to your spaced repetition system.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I recommend you 
&lt;a href=&#34;https://andymatuschak.org/prompts/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;read Andy Matuschak&amp;rsquo;s notes on &amp;ldquo;How to write good prompts&amp;rdquo;&lt;/a&gt; for tips on how to create good flashcards. 
&lt;a href=&#34;https://ncase.me/remember/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Nicky Case&amp;rsquo;s comic: &amp;ldquo;How to Remember Anything Forever-ish&amp;rdquo;&lt;/a&gt; also has good suggestions for how to create good questions for spaced repetition.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How to do a Review Session:&lt;/strong&gt; Visit your &amp;ldquo;Spaced Repetition&amp;rdquo; page to figure out what session number to do. Increment the session number, and use the schedule to determine which Leitner boxes you&amp;rsquo;ll be looking at in this session. Remember, do the Leitner boxes in decreasing order of their number.&lt;/p&gt;
&lt;p&gt;For each Leitner box, visit its page in Roam. All your questions will appear in the Linked References section of the page.&lt;/p&gt;
&lt;p&gt;Go through the questions one by one. If you get the answer correct, increment the box number by 1. If you get the answer incorrect or struggle with it, set the tag back to &amp;ldquo;#[[Leitner Box 1]]&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t worry about sending things back to box 1; you&amp;rsquo;ll see those questions very often and soon they&amp;rsquo;ll be back in the higher numbered boxes again!&lt;/p&gt;
&lt;h2 id=&#34;enhancements-beyond-the-default-system&#34;&gt;Enhancements Beyond the Default System&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve made several changes to the default Leitner Box system to improve it to my taste. You&amp;rsquo;re welcome to use them!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Leitner Boxes 0 and $\infty$:&lt;/strong&gt; I use an extra box, &amp;ldquo;Leitner Box 0&amp;rdquo; for flashcards that I&amp;rsquo;m not ready to put into my rotation yet. I try to only add at most 10 cards a day to keep the total review workload low. If I have more cards than this, I keep them in Box 0 until I&amp;rsquo;m ready to start studying them, at which point I move them to Box 1.&lt;/p&gt;
&lt;p&gt;Leitner Box $\infty$ is for cards that have graduated from Box 7. In theory, I will remember these cards for the rest of my life.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Extra box 5s, 6s, and 7s:&lt;/strong&gt; I have decided to create two Box 5s (named 5A and 5B), four Box 6s (6A, 6B, 6C, and 6D), and eight Box 7s (7A through 7H). This prevents any individual review session from accumulating too many cards.&lt;/p&gt;
&lt;p&gt;I ran a simulation and under the default system, adding 10 new cards a day and getting 95% of cards correct, some review sessions will require reviewing over 700 cards! Under the enhanced system, the longest review session will only ever be 140 cards (and most review sessions are much shorter than that).&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the modified schedule that allows me to use these extra boxes:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://firebasestorage.googleapis.com/v0/b/firescript-577a2.appspot.com/o/imgs%2Fapp%2Fplayground%2F_dSM-MMp85.png?alt=media&amp;amp;token=b3682748-8ea4-4444-97df-0c4592beb1ff&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://firebasestorage.googleapis.com/v0/b/firescript-577a2.appspot.com/o/imgs%2Fapp%2Fplayground%2FhFRPfzGpwy.png?alt=media&amp;amp;token=20b7f689-4117-4901-a806-846b0d099d7d&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;To use this enhanced schedule, first use the review session number to figure out which column of colored circles to look at. As before, a red circle indicates Leitner Box 1, a yellow circle indicates Leitner Box 2, etc. If the circle has a letter inside it, that means to review that particular variant of the box. E.g. a blue circle with a &amp;ldquo;B&amp;rdquo; inside means to review Leitner box 5B. The arrow to the right of a box indicates which box you should move the card to if you get it correct. E.g. in review session &amp;ldquo;51&amp;rdquo; you should review box 5B and move correct cards to box 6D; you should then review boxes 2 and 1 as usual.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Embed the box list:&lt;/strong&gt; I use Roam Research&amp;rsquo;s &amp;ldquo;embed block&amp;rdquo; feature to embed a list of all Leitner Boxes onto all my Leitner Box pages. This makes it easy to quickly navigate from any box to any other box. I couldn&amp;rsquo;t think of a good way to include this in the template, so you&amp;rsquo;ll have to add this yourself if you want to include it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Enhanced Template&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can 
&lt;a href=&#34;https://pastebin.com/zvjFKZAb&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;access the enhanced version of the template here&lt;/a&gt;. It includes more Leitner boxes and the more complicated schedule. To use it, simply paste it into a new page in Roam Research, e.g. &amp;ldquo;Spaced Repetition&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;spaced-repetition-alternatives&#34;&gt;Spaced Repetition Alternatives&lt;/h2&gt;
&lt;p&gt;There are multiple ways of doing spaced repetition in Roam, of which this is just one. Note that most spaced repetition systems in Roam Research use the &amp;ldquo;delta&amp;rdquo; feature. However, we are not using this feature. CortexFutura provides 
&lt;a href=&#34;https://www.cortexfutura.com/preliminary-spaced-repetition-roam/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;a way of using the delta feature for spaced repetition here&lt;/a&gt;. Roam Toolkit provides another system for doing spaced repetition in Roam, which you can 
&lt;a href=&#34;https://www.youtube.com/watch?v=08o8q_bOedw&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;view on YouTube here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One of the most popular spaced repetition systems is called 
&lt;a href=&#34;https://apps.ankiweb.net/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Anki&lt;/a&gt;. It&amp;rsquo;s great for language learning. I&amp;rsquo;d be remiss not to mention it. The reason I prefer doing spaced repetition directly in Roam is that the friction to creating cards is much lower in Roam for me, since I&amp;rsquo;m taking notes and writing my ideas in there already.&lt;/p&gt;
&lt;p&gt;Additionally RemNote, a competitor note-taking tool to Roam, also offers a highly configurable spaced repetition system out-of-the-box.&lt;/p&gt;
&lt;p&gt;For more, consider joining the conversation in the 
&lt;a href=&#34;https://roamresearch.slack.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Roam Research Slack&lt;/a&gt; &amp;ldquo;spaced-repetition&amp;rdquo; channel.&lt;/p&gt;
&lt;h2 id=&#34;two-advantages-of-this-system-over-traditional-spaced-repetition-systems&#34;&gt;Two advantages of this system over traditional spaced repetition systems&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lower friction:&lt;/strong&gt; Creating cards directly in your note-taking app is substantially easier than needing to task switch to create cards. This lower mental overhead makes it easier to keep using spaced repetition for an extended period of time. I started using it two months ago myself, so finger&amp;rsquo;s crossed it indeed is something I keep up for much longer! 🤞&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Robustness to vacations:&lt;/strong&gt; In traditional spaced repetition systems, taking a break for a day, week, or month, can be ruinous to your spaced repetition rhythm. After coming back from the break, you find you have too many cards to review all at once, which can be a real motivation drain. Instead of organizing cards by &lt;strong&gt;date&lt;/strong&gt;, my system organizes them by &lt;strong&gt;review session number.&lt;/strong&gt; This means that if you skip a day or a week, your reviews simply get pushed back. The review session number won&amp;rsquo;t go up while you&amp;rsquo;re away. You can even split a review session over multiple days if you like. No trouble! You&amp;rsquo;ll never be left with a review session that&amp;rsquo;s too big to handle.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;additional-resources&#34;&gt;Additional Resources&lt;/h2&gt;
&lt;p&gt;
&lt;a href=&#34;https://ncase.me/remember/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Nicky Case&amp;rsquo;s comic: &amp;ldquo;How to Remember Anything Forever-ish&amp;rdquo;&lt;/a&gt; is what inspired me to start using spaced repetition in my life.&lt;/p&gt;
&lt;p&gt;
&lt;a href=&#34;https://withorbit.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Andy Matuschak&amp;rsquo;s &amp;ldquo;Orbit&amp;rdquo; system&lt;/a&gt; enables writers to incorporate spaced repetition directly into their writing, to help their readers remember what they learned forever. You can read 
&lt;a href=&#34;https://quantum.country/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Quantum Country&lt;/a&gt; to learn quantum computing and give it a try. You could also 
&lt;a href=&#34;https://andymatuschak.org/prompts/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;read his tips for &amp;ldquo;How to write good prompts&amp;rdquo;&lt;/a&gt;, which is also written with Orbit.&lt;/p&gt;
&lt;p&gt;You can 
&lt;a href=&#34;https://apps.ankiweb.net/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;get Anki here&lt;/a&gt; or 
&lt;a href=&#34;https://www.remnote.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;try RemNote here&lt;/a&gt;. I also have a dozen+ other 
&lt;a href=&#34;https://davidbieber.com/snippets/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;snippets about Roam here&lt;/a&gt; (
&lt;a href=&#34;https://davidbieber.com/snippets/2019-12-25-introducing-snippets/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;what&amp;rsquo;s a “snippet”?&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&#34;get-in-touch&#34;&gt;Get in touch&lt;/h2&gt;
&lt;p&gt;I love a good discussion about spaced repetition. You can email me at 
&lt;a href=&#34;mailto:david810&amp;#43;spaced-repetition@gmail.com&#34;&gt;david810+spaced-repetition@gmail.com&lt;/a&gt;, find me on Twitter (
&lt;a href=&#34;https://twitter.com/@Bieber&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;@Bieber&lt;/a&gt;), or join the 
&lt;a href=&#34;https://roamresearch.slack.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Roam slack&lt;/a&gt; to keep the conversation going.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Programmatically Accessing Chrome&#39;s “Tabs from other devices” Data</title>
      <link>https://davidbieber.com/snippets/2021-01-01-programmatically-accessing-chromes-tabs-from-other-devices-data/</link>
      <pubDate>Fri, 01 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2021-01-01-programmatically-accessing-chromes-tabs-from-other-devices-data/</guid>
      
      <description>&lt;p&gt;I use Google Chrome on my Mac laptop and on my iPhone, and I&amp;rsquo;m logged in to my Google account in both places with syncing turned on. If I go to &amp;ldquo;chrome://history/syncedTabs&amp;rdquo; on my computer I can see what tabs I have open on my phone. Now, I&amp;rsquo;d like to access this data programatically.&lt;/p&gt;
&lt;p&gt;With the help of &lt;code&gt;grep&lt;/code&gt;, I&amp;rsquo;ve figured out that this data is stored in &lt;code&gt;~/Library/Application Support/Google/Chrome/Profile 1/Sync Data/LevelDB/&lt;/code&gt; (Probably for most people the path would be &lt;code&gt;~/Library/Application Support/Google/Chrome/Default/Sync Data/LevelDB/&lt;/code&gt;). Be careful to escape the spaces in the file path!&lt;/p&gt;
&lt;p&gt;To read from a LevelDB database, I first installed leveldb with &lt;code&gt;brew install leveldb&lt;/code&gt;, and then I installed a Python LevelDB client: &lt;code&gt;pip install plyvel&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I then use little Python scripts like the following to access the data, though I haven&amp;rsquo;t quite figured out (1) how to properly parse the data; it&amp;rsquo;s probably a protocol buffer, or (2) exactly how it&amp;rsquo;s organized, so I don&amp;rsquo;t know exactly which keys to look at.&lt;/p&gt;
&lt;p&gt;Note that I have copied the LevelDB folder to a new location before opening it. This ensures that Chrome doesn&amp;rsquo;t have a lock on any of the files in the copy, and that even if we make a mistake we won&amp;rsquo;t damage Chrome&amp;rsquo;s data.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import plyvel
import re
import os

db = plyvel.DB(os.path.expanduser(&amp;quot;~/Profile1/Sync Data/LevelDB/&amp;quot;))

for key, value in db.iterator():
  if b&#39;sessions-dt&#39; in key:
    data = re.findall(b&#39;https?://[\x20-\x7F]+&#39;, value)
    if data:
      print(key)
      print(data)
      print()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This script prints out the URLs of the synced tabs, plus some extra data and extra characters. To do this properly, the next step will be to figure out how to parse the data.&lt;/p&gt;
&lt;p&gt;Why do I want to programmatically figure out which tabs are open on my phone? I want to do automatic distraction detection. When I&amp;rsquo;m on a distracting website like Twitter for several minutes during a period when I mean to be focusing on something else, I&amp;rsquo;d like Bieber Bot to be able to stage an intervention to help me focus.&lt;/p&gt;
&lt;p&gt;A variation on the script above should be sufficient for figuring out if I have any distracting websites open on my phone. So, I may be able to implement the distraction detection and intervention logic even before getting the parsing done correctly.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Where do thoughts come from? A thought experiment.</title>
      <link>https://davidbieber.com/snippets/2020-12-29-where-do-thoughts-come-from-a-thought-experiment/</link>
      <pubDate>Tue, 29 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-12-29-where-do-thoughts-come-from-a-thought-experiment/</guid>
      
      <description>&lt;p&gt;This snippet details a thought experiment I&amp;rsquo;ve been encouraging people to do for years. It&amp;rsquo;s simple, and should only take a few minutes of your time. The purpose of the thought experiment is to better understand where your thoughts come from.&lt;/p&gt;
&lt;p&gt;There are just four steps in the experiment: (1) think thoughts, (2) remember those thoughts and write them down, (3) determine their causes, (4) categorize those causes.&lt;/p&gt;
&lt;p&gt;Let me explain in more detail.&lt;/p&gt;
&lt;p&gt;(1) To start the experiment, &lt;strong&gt;think thoughts&lt;/strong&gt; for one minute. You can set a timer. During this minute, it&amp;rsquo;s okay for your mind to wander. It isn&amp;rsquo;t important what you think about. During this time you&amp;rsquo;re just thinking, not writing.&lt;/p&gt;
&lt;p&gt;(2) Once the minute is over, try to &lt;strong&gt;remember all the thoughts&lt;/strong&gt; you had during that minute; &lt;strong&gt;write them all down&lt;/strong&gt; in a list. As much as possible, put that list in chronological order. It may take much more than a minute to remember and write down all those thoughts. This step can be difficult; try to be as thorough as possible. You may surprise yourself by at first not remembering thinking something, and then only after thinking hard trying to remember it finding it becoming clear as your recollection improves.&lt;/p&gt;
&lt;p&gt;(3) &lt;strong&gt;Determine the causes&lt;/strong&gt; of the thoughts. For each thought on the list, try to determine &lt;strong&gt;why&lt;/strong&gt; that thought arose. What was the cause of that thought arising in your mind? For some thoughts the cause will be obvious. For others it may not be obvious at all; don&amp;rsquo;t give up. Really spend some time trying to determine why you thought all the things you thought. I believe there is always a reason.&lt;/p&gt;
&lt;p&gt;(4) Finally, look over the complete list of reasons. &lt;strong&gt;Come up with categories&lt;/strong&gt; for the reasons. Maybe one thought arose because something you saw or smelled triggered a memory. Maybe other thoughts arose because one word sounds like another. Be creative in how you categorize thoughts. There&amp;rsquo;s no right or wrong way to do this.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all. This whole experiment can take less than half an hour, less or more depending on how into it you get and how detailed you are. While it doesn&amp;rsquo;t take that much time, it can be mentally draining. Have some water, relax, treat yourself when you&amp;rsquo;re done :).&lt;/p&gt;
&lt;p&gt;As I mentioned, the purpose of the experiment is to better understand where thoughts come from. Individually, this experiment helps us better understand ourselves through introspection. Through sharing the results with each other, it can also help us better understand each other.&lt;/p&gt;
&lt;p&gt;I would be absolutely delighted to hear from you if you do this experiment. You can reach me at 
&lt;a href=&#34;mailto:david810&amp;#43;thinking@gmail.com&#34;&gt;david810+thinking@gmail.com&lt;/a&gt;. Feel free to send me your thoughts, causes, and categories from the experiment (or just a subset if any of that is too personal to share). And I would of course also love to hear your thoughts about the experiment too, or your thoughts on thinking. Really, don&amp;rsquo;t hesitate to get in touch.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Publishing Blog Posts from Roam Research Quickly and Automatically</title>
      <link>https://davidbieber.com/snippets/2020-12-28-publishing-blog-posts-from-roam-research-quickly-and-automatically/</link>
      <pubDate>Mon, 28 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-12-28-publishing-blog-posts-from-roam-research-quickly-and-automatically/</guid>
      
      <description>&lt;p&gt;I thought today I would attempt a proper treatment of my latest automatic &amp;ldquo;
&lt;a href=&#34;https://davidbieber.com/snippets/&#34;&gt;snippet&lt;/a&gt;&amp;rdquo; publishing system. It uses JavaScript embedded directly in Roam Research to publish snippets to my website with low latency as I write them.&lt;/p&gt;
&lt;h2 id=&#34;prior-methods&#34;&gt;Prior methods&lt;/h2&gt;
&lt;p&gt;Previously I&amp;rsquo;ve written a system to allow 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-09-27-posting-snippets-from-my-phone/&#34;&gt;Bieber Bot to publish snippets that I send him&lt;/a&gt;, and followed that up with a 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-10-06-introducing-the-snippet-queue/&#34;&gt;snippet queue&lt;/a&gt; to allow me to schedule the publication of my snippets.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve then also implemented two previous automatic snippet publishers from Roam. The first used my roam-to-git backup to detect new or updated snippets. The second used a puppeteer instance to occasionally check Roam for new or updated snippets.&lt;/p&gt;
&lt;p&gt;That makes this my third implementation of automatic snippet publishing from Roam, and my fifth automatic snippet publishing project to date. It&amp;rsquo;s the fastest yet, going from Roam to live on the website in just 90 seconds.&lt;/p&gt;
&lt;h2 id=&#34;room-for-improvement&#34;&gt;Room for improvement&lt;/h2&gt;
&lt;p&gt;Why was publishing through Bieber Bot not enough? Roam is a natural place to write, and I find I write quite a bit more here than I do elsewhere. Since snippets are 
&lt;a href=&#34;https://davidbieber.com/snippets/2019-12-30-writing-for-no-audience/&#34;&gt;all about lowering the barrier of entry to writing&lt;/a&gt;, supporting writing snippets in Roam seems natural.&lt;/p&gt;
&lt;p&gt;Why was the roam-to-git backup based automatic publication system insufficient? While, adequate, the latency between writing a snippet and having it show up on my website was multiple hours. The roam-to-git backups only trigger every hour, and fail about 30% of the time. The script to use those backups to publish to my website would also only run every hour. Their combined schedules meant it could be 2-3 or more hours between writing a snippet and being able to share the link to it. Lowering this latency would give me more freedom to quickly write and share snippets, and also to iterate on a published snippet. Fast iteration is powerful.&lt;/p&gt;
&lt;p&gt;Finally, why was the puppeteer-based approach insufficient. While this approach had the potential to bring the publication latency down considerably, in practice I scheduled in to run about hourly, since a headless browser is a computationally heavy piece of software.&lt;/p&gt;
&lt;h2 id=&#34;the-new-approach-roamjs&#34;&gt;The new approach: &amp;ldquo;roam/js&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;Roam Research allows you to write JavaScript to run directly in Roam. My new approach is to run JavaScript in Roam to detect when a new snippet is written or when an existing snippet gets updated. When this occurs, the script will trigger a GitHub Action, using the snippet content and metadata as input. The GitHub Action will commit the snippet to my website&amp;rsquo;s git repo, and trigger a rebuilding of my website. It does everything except the final deploy to the webserver automatically; that final step waits for me to send a message &amp;ldquo;Deploy snippets!&amp;rdquo; to Bieber Bot, upon receipt of which the final deploy step is performed and the website is updated.&lt;/p&gt;
&lt;p&gt;Using this approach it takes only 90 seconds between writing or editing a snippet and having it live on my website.&lt;/p&gt;
&lt;h2 id=&#34;detecting-new-snippets-and-snippet-updates&#34;&gt;Detecting new snippets and snippet updates&lt;/h2&gt;
&lt;p&gt;There are two key pieces to how I detect new and updated snippets. The first is a &amp;ldquo;mutation observer&amp;rdquo;. A mutation observer is an object in JavaScript that allows you to schedule events to occur when DOM changes are made to a website. In Roam, the DOM is modified when the user makes edits, and so DOM changes can indicate that the user has made a change to their notes.&lt;/p&gt;
&lt;p&gt;We would like to detect when a snippet is created or edited. So, we write a function that detects if a snippet has been created or edited since the last time it was called, and we use a mutation observer to call this function when the DOM changes.&lt;/p&gt;
&lt;p&gt;Since DOM changes can occur very frequently in Roam, we use a technique called 
&lt;a href=&#34;https://davidwalsh.name/javascript-debounce-function&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;debouncing&lt;/a&gt; to limit the number of calls to this detection function during periods of many consecutive DOM changes.&lt;/p&gt;
&lt;p&gt;How do we detect if a snippet has been created or edited? Roam Research provides a datalog API that allows us to query our entire Roam graph using a logic programming language. You can 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-12-22-datalog-queries-for-roam-research/&#34;&gt;learn more about how this works here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I mark a snippet for publication by tagging it with both the &amp;ldquo;Snippets&amp;rdquo; tag, and the &amp;ldquo;ok-to-publish&amp;rdquo; tag. This query detects those blocks that are part of a publishable snippet.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;ancestor = `[ 
 [(ancestor ?child ?parent) 
  [?parent :block/children ?child]] 
 [(ancestor ?child ?ancestor) 
  [?parent :block/children ?child] 
  (ancestor ?parent ?ancestor)]]
]`;

block_info = window.roamAlphaAPI.q(`[
  :find ?uid ?child_text ?child_uid ?parent_uid ?order
  :in $ %
  :where
  [?block :block/uid ?uid]
  [?block :block/string ?string]
  [?block :block/refs ?snippets]
  [?block :block/refs ?publish]
  [?snippets :node/title &amp;quot;Snippets&amp;quot;]
  [?publish :node/title &amp;quot;ok-to-publish&amp;quot;]
  (ancestor ?child ?block)
  [?parent :block/children ?child]
  [?parent :block/uid ?parent_uid]
  [?child :block/uid ?child_uid]
  [?child :block/order ?order]
  [?child :block/string ?child_text]
]`, ancestor);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&amp;rsquo;s break down what&amp;rsquo;s happening in this query. First, there&amp;rsquo;s the &lt;code&gt;ancestor&lt;/code&gt; rule. The Roam datalog schema only includes a blocks immediate children; the &lt;code&gt;ancestor&lt;/code&gt; rule allows us to query for all a block&amp;rsquo;s descendants or ancestors, not just the immediate ones. It does this through the recursive definition of &amp;ldquo;ancestor&amp;rdquo; shown, which you can read as &amp;ldquo;An ancestor of ?child is ?parent if ?parent has a child ?child, AND ALSO an ancestor of ?child is ?ancestor if there exists some ?parent satisfying both ?parent has a child ?child, and ?parent has ?ancestor as an ancestor.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The rest of the query (lines 10-24) finds blocks that are the descendants of a block ?block that&amp;rsquo;s tagged with both &amp;ldquo;Snippets&amp;rdquo; and &amp;ldquo;ok-to-publish.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Since Datalog returns the results in an arbitrary order, we need to use the :block/order attribute to reconstruct the proper order of the blocks that comprise the snippet. The logic for this isn&amp;rsquo;t shown, but don&amp;rsquo;t hesitate to reach out if this interests you!&lt;/p&gt;
&lt;p&gt;Finally, our mutation observer keeps track of the text of each of the snippets, and if any of them change or if a new snippet is introduced, it triggers a GitHub Action to deploy the snippet to my website.&lt;/p&gt;
&lt;h2 id=&#34;writing-a-github-action-to-update-my-website&#34;&gt;Writing a GitHub Action to update my website&lt;/h2&gt;
&lt;p&gt;My website uses a static site generator, Hugo. So, updating my website consists of adding a markdown file to 
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;its GitHub repo&lt;/a&gt;, rebuilding the site by running Hugo, and then pushing the generated static files up to my server. All of these steps can be automated in a GitHub action.&lt;/p&gt;
&lt;h3 id=&#34;triggering-a-github-action-from-roam-research&#34;&gt;Triggering a GitHub Action from Roam Research&lt;/h3&gt;
&lt;p&gt;To trigger a GitHub Action from Roam Research, I set up the action to trigger on &amp;ldquo;repository_dispatch&amp;rdquo; events. I created a personal authentication token, and then use the following JavaScript to trigger the GitHub Action:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;function publishSnippetRaw(uid, title, date, content) {
  const data = {
    &amp;quot;event_type&amp;quot;: &amp;quot;snippet-update&amp;quot;,
    &amp;quot;client_payload&amp;quot;: {
      &amp;quot;uid&amp;quot;: uid,
      &amp;quot;title&amp;quot;: title,
      &amp;quot;date&amp;quot;: date,
      &amp;quot;content&amp;quot;: content,
    }
  };
  fetch(
    &amp;quot;https://api.github.com/repos/dbieber/davidbieber.com/dispatches&amp;quot;,
    {
      headers: {
        Accept: &amp;quot;application/vnd.github.everest-preview+json&amp;quot;,
        Authorization: &amp;quot;token PERSONAL_AUTHENTICATION_TOKEN&amp;quot;,
      },
      method: &#39;POST&#39;,
      body: JSON.stringify(data),
    }
  );
}
const publishSnippet = debounce(publishSnippetRaw, 15000, true);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This call to &lt;code&gt;fetch&lt;/code&gt; starts the GitHub Action running on a GitHub server within seconds.&lt;/p&gt;
&lt;h3 id=&#34;accepting-inputs-in-a-github-action&#34;&gt;Accepting inputs in a GitHub Action&lt;/h3&gt;
&lt;p&gt;You will notice that &lt;code&gt;data&lt;/code&gt; contains a &amp;ldquo;client_payload&amp;rdquo; in the above JavaScript. To accept inputs in the GitHub Action, I access the data from the client_payload and set it to an environment variable in the Action YAML like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;env:
  SNIPPET_UID: ${{ github.event.client_payload.uid }}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Environment variables like this can then be used by the steps in the action. This allows me to pass the contents of the new/modified snippet to the GitHub Action, which is everything needed for automating its publication.&lt;/p&gt;
&lt;p&gt;The GitHub Action writes the markdown file, commits it to the repository, runs hugo to regenerate the static files for the website, and commits those to the appropriate part of the repo as well. The only step remaining at this point is pushing the new files up to my server to serve.&lt;/p&gt;
&lt;h2 id=&#34;deploying-with-ansible&#34;&gt;Deploying with Ansible&lt;/h2&gt;
&lt;p&gt;I use 
&lt;a href=&#34;https://www.ansible.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ansible&lt;/a&gt; to deploy my website to its lone server. 
&lt;a href=&#34;https://davidbieber.com/projects/bieber-bot/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Bieber Bot&lt;/a&gt; is also quite capable of using Ansible. So, we have an arrangement where I tell Bieber Bot when to redeploy my website, and he does so for me. This way I can deploy my website even when I&amp;rsquo;m on the go and not at a computer; I just message him using my phone.&lt;/p&gt;
&lt;p&gt;All steps, from the last keystroke of writing a snippet to having it show up live on my website, together take about 90 seconds. This is a significant quality-of-life improvement over the multi-hour latency of just a few days ago. I&amp;rsquo;m hopeful that the result is I&amp;rsquo;ll write even more.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Even Faster Snippet Publishing from Roam</title>
      <link>https://davidbieber.com/snippets/2020-12-27-even-faster-snippet-publishing-from-roam/</link>
      <pubDate>Sun, 27 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-12-27-even-faster-snippet-publishing-from-roam/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;ve set up a GitHub action to enable even faster automatic publishing of snippets from Roam. This is a test-snippet I&amp;rsquo;m using while writing the auto-publisher.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see how it behaves if I&amp;rsquo;m editing an existing snippet routinely for a while.&lt;/p&gt;
&lt;p&gt;If it works as intended, the snippet will update itself on GitHub after I stop typing for several seconds. I&amp;rsquo;ve now stopped typing, we&amp;rsquo;ll see what happens.&lt;/p&gt;
&lt;p&gt;It worked! 
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/commit/1f1ad4680e1d538f699cf2cd420f0c04a4bf528a&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Here&amp;rsquo;s the commit&lt;/a&gt; that was made automatically after I finished the previous sentence.&lt;/p&gt;
&lt;p&gt;This will make publishing snippets &lt;strong&gt;even easier&lt;/strong&gt; going forward. It also means I don&amp;rsquo;t need to keep a puppeteer instance constantly live with Roam open like I&amp;rsquo;d originally planned for.&lt;/p&gt;
&lt;p&gt;The total latency from writing to publication is now just 90 seconds. So you could be reading this mere minutes after I write it!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Python&#39;s strip, lstrip, and rstrip in JavaScript</title>
      <link>https://davidbieber.com/snippets/2020-12-26-pythons-strip-lstrip-and-rstrip-in-javascript/</link>
      <pubDate>Sat, 26 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-12-26-pythons-strip-lstrip-and-rstrip-in-javascript/</guid>
      
      <description>&lt;p&gt;Python provides some convenient functions for manipulating strings: &lt;code&gt;strip&lt;/code&gt;, &lt;code&gt;lstrip&lt;/code&gt;, and &lt;code&gt;rstrip&lt;/code&gt;. Recently I was writing some JavaScript and wanted to use &lt;code&gt;rstrip&lt;/code&gt;. So, I&amp;rsquo;ve implemented all three. Here they are:&lt;/p&gt;
&lt;h2 id=&#34;the-python-strip-method-in-javascript&#34;&gt;The Python strip method in JavaScript&lt;/h2&gt;
&lt;p&gt;In Python, &lt;code&gt;strip&lt;/code&gt; removes whitespace from the beginning or end of a string. This is commonly called &amp;ldquo;trim&amp;rdquo; in JavaScript, and is provided as a builtin in most modern browsers. You may need to implement it yourself if you want to support older browsers though. Here&amp;rsquo;s one possible implementation, 
&lt;a href=&#34;https://www.w3schools.com/python/ref_string_strip.asp&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;courtesy of W3Schools&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;function trim(x) {
  return x.replace(/^\s+|\s+$/gm, &#39;&#39;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Python &lt;code&gt;strip&lt;/code&gt; method optionally accepts an argument, &amp;ldquo;characters&amp;rdquo;, and strips all instances of those characters from the left and right sides of the input string. We implement that here.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;function trim(x, characters) {
  var start = 0;
  while (characters.indexOf(x[start]) &amp;gt;= 0) {
    start += 1;
  }
  var end = x.length - 1;
  while (characters.indexOf(x[end]) &amp;gt;= 0) {
    end -= 1;
  }
  return x.substr(start, end - start + 1);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This may not be the most efficient implementation (the calls to indexOf in particular could be made faster), but it gets the job done.&lt;/p&gt;
&lt;h2 id=&#34;the-python-rstrip-method-in-javascript&#34;&gt;The Python rstrip method in JavaScript&lt;/h2&gt;
&lt;p&gt;The rstrip method behaves like strip, but only removes spaces (or the specified characters) from the right side of the input string. We implement this in JavaScript now, calling it &amp;ldquo;rtrim&amp;rdquo; for consistency with the name &amp;ldquo;trim&amp;rdquo;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;function rtrim(x) {
  // This implementation removes whitespace from the right side
  // of the input string.
  return x.replace(/\s+$/gm, &#39;&#39;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We now implement rtrim a second time, now accepting &amp;ldquo;characters&amp;rdquo; as input:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;function rtrim(x, characters) {
  var start = 0;
  var end = x.length - 1;
  while (characters.indexOf(x[end]) &amp;gt;= 0) {
    end -= 1;
  }
  return x.substr(0, end + 1);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;the-python-lstrip-method-in-javascript&#34;&gt;The Python lstrip method in JavaScript&lt;/h2&gt;
&lt;p&gt;Finally we provide a port of Python&amp;rsquo;s lstrip to JavaScript, calling it ltrim. We again provide one version that strips only whitespace, and a second that strips the provided &amp;ldquo;characters&amp;rdquo; input.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;function ltrim(x) {
  // This implementation removes whitespace from the left side
  // of the input string.
  return x.replace(/^\s+/gm, &#39;&#39;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We now implement ltrim a second time, now accepting &amp;ldquo;characters&amp;rdquo; as input:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;function ltrim(x, characters) {
  var start = 0;
  while (characters.indexOf(x[start]) &amp;gt;= 0) {
    start += 1;
  }
  var end = x.length - 1;
  return x.substr(start);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;example-usage&#34;&gt;Example Usage&lt;/h2&gt;
&lt;p&gt;Here are some example usages of the above functions.&lt;/p&gt;
&lt;p&gt;First, using the implementations that strip spaces:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;trim(&#39;   Hello world!   &#39;) === &#39;Hello world!&#39;;
ltrim(&#39;   Hello world!   &#39;) === &#39;Hello world!   &#39;;
rtrim(&#39;   Hello world!   &#39;) === &#39;   Hello world!&#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Second, using the implementations that strip the specified characters:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;trim(&#39;Buzzzzzz&#39;, &#39;Bz&#39;) === &#39;u&#39;;
ltrim(&#39;Buzzzzzz&#39;, &#39;Bz&#39;) === &#39;uzzzzzz&#39;;
rtrim(&#39;Buzzzzzz&#39;, &#39;Bz&#39;) === &#39;Bu&#39;;
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Improving Roam Snippet Publishing Speeds</title>
      <link>https://davidbieber.com/snippets/2020-12-23-improving-roam-snippet-publishing-speeds/</link>
      <pubDate>Wed, 23 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-12-23-improving-roam-snippet-publishing-speeds/</guid>
      
      <description>&lt;p&gt;Hey folks, I have a 
&lt;a href=&#34;https://davidbieber.com/projects/bieber-bot/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;workflow&lt;/a&gt; for automatically publishing &amp;ldquo;
&lt;a href=&#34;https://davidbieber.com/snippets/2019-12-30-writing-for-no-audience/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;snippets&lt;/a&gt;&amp;rdquo; to my website from Roam. Currently there&amp;rsquo;s a multi-hour latency between writing a snippet and when it appears on my website. In this snippet I&amp;rsquo;m going to muse about / ask questions about how to use &lt;strong&gt;puppeteer&lt;/strong&gt; to bring this latency down considerably. This&amp;rsquo;ll be my first time using puppeteer, so help appreciated. Read on!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://a.slack-edge.com/production-standard-emoji-assets/10.2/apple-small/1f62e@2x.png&#34; alt=&#34;😮&#34;&gt;&lt;/p&gt;
&lt;p&gt;The current system relies on my git-to-roam backup, which runs every hour and fails some fraction of the time.&lt;/p&gt;
&lt;p&gt;So, to bring the latency down, the idea is to use pyppeteer (the python puppeteer bindings) to log into Roam in a headless browser.&lt;/p&gt;
&lt;p&gt;This will monitor Roam for new (or modified) snippets, and will publish them to my website.&lt;/p&gt;
&lt;p&gt;A snippet is OK to publish if its tagged with both &amp;ldquo;Snippets&amp;rdquo; and &amp;ldquo;ok-to-publish&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;So, first question: has anyone done this before? B/c if someone&amp;rsquo;s already gotten all the CSS/XPATH selectors for logging in, navigating, etc, that could save me some time&lt;/p&gt;
&lt;p&gt;Another important thing I&amp;rsquo;m thinking about: are there problems keeping an instance of Roam open in a headless browser could cause?&lt;/p&gt;
&lt;p&gt;E.g. I hear about occasional data loss which seems related to having out-of-date instances of Roam open on other machines &amp;ndash; e.g. maybe the out of date Roam comes back online and overwrites new content with older blank content?&lt;/p&gt;
&lt;p&gt;I think I&amp;rsquo;ll make my headless Roam instances relatively-short lived (&amp;lt;10 minutes) just in case.&lt;/p&gt;
&lt;p&gt;I think the strategy I&amp;rsquo;ll take will be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Log in to Roam in headless browser&lt;/li&gt;
&lt;li&gt;Run datalog query in javascript to check for new/updated snippets.&lt;/li&gt;
&lt;li&gt;Run that query fairly frequently (e.g. every few seconds) in order to detect snippets as soon as they&amp;rsquo;re available&lt;/li&gt;
&lt;li&gt;Debounce, so that if a snippet is actively changing its only deployed ~twice, not 100 times&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And then every 10 minutes or so I&amp;rsquo;ll have it take a short breather and refresh&lt;/p&gt;
&lt;p&gt;Abhay suggested using the alpha API for this rather than puppeteering. &lt;img src=&#34;https://a.slack-edge.com/production-standard-emoji-assets/10.2/apple-medium/1f64f@2x.png&#34; alt=&#34;🙏&#34;&gt;&lt;/p&gt;
&lt;p&gt;I think I&amp;rsquo;ll get started on the puppeteer implementation now though anyway, even if the API ends up being a better way of doing this in the near future.&lt;/p&gt;
&lt;p&gt;Update:&lt;/p&gt;
&lt;p&gt;I have a first draft that handles log in and running the query to detect publishable material (blocks with the appropriate two tags).&lt;/p&gt;
&lt;p&gt;Not sure how reliable login is as I had some hiccups getting it working.&lt;/p&gt;
&lt;p&gt;And the headless browser seems very slow to notice changes to the Roam graph compared to what I&amp;rsquo;m used to.&lt;/p&gt;
&lt;p&gt;So instead of checking every few seconds, I think I&amp;rsquo;ll just check once a minute or so, refreshing either every time or every few times.&lt;/p&gt;
&lt;p&gt;Unexpected snag: I get the children of a block but I don&amp;rsquo;t know how to put them in the proper order!&lt;/p&gt;
&lt;p&gt;(with datalog)&lt;/p&gt;
&lt;p&gt;I could navigate to the block and look at the dom&amp;hellip; but hopefully I don&amp;rsquo;t need to do that.&lt;/p&gt;
&lt;p&gt;Looks like there is an &amp;ldquo;order&amp;rdquo; attribute, so this will be doable. Might be messy though.&lt;/p&gt;
&lt;p&gt;If I&amp;rsquo;m understanding right, :block/order gives the index of a block into its parents children.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re good! &lt;img src=&#34;https://a.slack-edge.com/production-standard-emoji-assets/10.2/apple-medium/1f44d@2x.png&#34; alt=&#34;👍&#34;&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re reading this on my website, it worked!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Datalog Queries for Roam Research</title>
      <link>https://davidbieber.com/snippets/2020-12-22-datalog-queries-for-roam-research/</link>
      <pubDate>Tue, 22 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-12-22-datalog-queries-for-roam-research/</guid>
      
      <description>&lt;p&gt;
&lt;a href=&#34;https://roamresearch.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Roam Research&lt;/a&gt; is an excellent note taking tool. One of its core features is &amp;ldquo;back links&amp;rdquo; &amp;ndash; any of your notes can easily references any of your other notes, and so all your notes end up linked together in an intricate graph structure. You can quickly see all the references to a note, hence the term &amp;ldquo;back link&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Roam exposes all of the information in your graph through a &lt;strong&gt;datalog API&lt;/strong&gt;. Datalog is a declarative programming language that lets you make queries about your graph.&lt;/p&gt;
&lt;h2 id=&#34;resources&#34;&gt;Resources&lt;/h2&gt;
&lt;p&gt;If you want to learn datalog, I recommend &lt;a href=&#34;http://www.learndatalogtoday.org/&#34;&gt;http://www.learndatalogtoday.org/&lt;/a&gt;. It teaches how to write datalog queries in 8 relatively short chapters chock full of examples.&lt;/p&gt;
&lt;p&gt;If you want to see how to use datalog specifically for Roam, you can head over to &lt;a href=&#34;https://www.putyourleftfoot.in/introduction-to-the-roam-alpha-api&#34;&gt;https://www.putyourleftfoot.in/introduction-to-the-roam-alpha-api&lt;/a&gt;. Or keep reading!&lt;/p&gt;
&lt;h2 id=&#34;examples&#34;&gt;Examples&lt;/h2&gt;
&lt;p&gt;In this snippet I include a number of examples of useful datalog queries for Roam Research.&lt;/p&gt;
&lt;h3 id=&#34;how-to-run-a-query&#34;&gt;How to Run a Query&lt;/h3&gt;
&lt;p&gt;Open the JavaScript console. Paste the query. Hit enter.&lt;/p&gt;
&lt;p&gt;To open the JavaScript console in Chrome, hit cmd-option-J on Mac or Ctrl-shift-J on Windows. For other systems, 
&lt;a href=&#34;https://www.google.com/search?q=how%20to%20open%20the%20javascript%20console&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;you can look up how to open it&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;pages-modified-today&#34;&gt;Pages modified today&lt;/h3&gt;
&lt;p&gt;This query returns a list of pages that have been modified today.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;let ancestorrule=`[ 
   [ (ancestor ?b ?a) 
        [?a :block/children ?b] ] 
   [ (ancestor ?b ?a) 
        [?parent :block/children ?b ] 
        (ancestor ?parent ?a) ] ] ]`;

let references = window.roamAlphaAPI.q(`[
  :find ?title
  :in $ ?start_of_day %
  :where
  [?page :node/title ?title]
  (ancestor ?block ?page)
  [?block :edit/time ?time]
  [(&amp;gt; ?time ?start_of_day)]
]`, new Date().setHours(0, 0, 0, 0), ancestorrule);

references.map(
  (data, index) =&amp;gt; {return `${data[0]}`;})
.join(&#39;\n&#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you run it in the javascript console, it should print out a list of pages that have been modified today.&lt;/p&gt;
&lt;h3 id=&#34;references-to-a-specific-page&#34;&gt;References to a specific page&lt;/h3&gt;
&lt;p&gt;This query finds all blocks referencing a specific page. Replace &amp;ldquo;Roam Research&amp;rdquo; in the query with the name of the page that you want to find the references of.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;let references = window.roamAlphaAPI.q(`[
  :find ?text
  :in $ ?title
  :where
  [?page :node/title ?title]
  [?e :block/refs ?page]
  [?e :block/string ?text]
]`, &#39;Roam Research&#39;);

references.map((data, index) =&amp;gt; {return data[0];}).join(&#39;\n&#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;all-blocks-on-a-specific-page&#34;&gt;All blocks on a specific page&lt;/h3&gt;
&lt;p&gt;This query finds all blocks on a specific page. Again replace &amp;ldquo;Roam Research&amp;rdquo; with the name of the page you&amp;rsquo;re interested in.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;let ancestorrule=`[ 
   [ (ancestor ?b ?a) 
        [?a :block/children ?b] ] 
   [ (ancestor ?b ?a) 
        [?parent :block/children ?b ] 
        (ancestor ?parent ?a) ] ] ]`;
let blocks = window.roamAlphaAPI.q(`[ 
  :find 
      ?string
  :in $ ?pagetitle % 
  :where 
      [?block :block/string ?string] 
      [?page :node/title ?pagetitle] 
      (ancestor ?block ?page)
  ]`, &amp;quot;Roam Research&amp;quot;, ancestorrule);

blocks.map((data, index) =&amp;gt; {return data[0];}).join(&#39;\n&#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;all-blocks-with-at-least-100-descendants&#34;&gt;All blocks with at least 100 descendants&lt;/h3&gt;
&lt;p&gt;This script finds all blocks with at least 100 descendants. The idea is that these blocks may have notes that are worth revisiting, either to summarize or reflect on. The threshold &amp;ldquo;100&amp;rdquo; is of course configurable at the top of the script.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;let threshold = 100;
let ancestorrule=`[ 
   [ (ancestor ?child ?parent) 
        [?parent :block/children ?child] ]
   [ (ancestor ?child ?a) 
        [?parent :block/children ?child ] 
        (ancestor ?parent ?a) ] ] ]`;

let large_blocks = window.roamAlphaAPI.q(`
[:find ?ancestor (count ?block)
  :in $ % 
  :where 
    [?ancestor :block/string]
    [?block :block/string]
    (ancestor ?block ?ancestor)]
`, ancestorrule).filter((data, index) =&amp;gt; {return data[1] &amp;gt;= threshold});

let results = window.roamAlphaAPI.q(`[
  :find ?text ?uid ?childcount
  :in $ ?block ?childcount
  :where
  [?block :block/string ?text]
  [?block :block/uid ?uid]
]`, large_blocks)
  
results.map((data, index) =&amp;gt; {return `((${data[1]})) (${data[2]})`}).join(&#39;\n&#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;support-and-debugging&#34;&gt;Support and Debugging&lt;/h2&gt;
&lt;p&gt;The &amp;ldquo;#querying&amp;rdquo; channel on the 
&lt;a href=&#34;https://roamresearch.slack.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Roam Research Slack&lt;/a&gt; is active and the community there is quite friendly. If you&amp;rsquo;re crafting or debugging a query, that&amp;rsquo;s a great place to ask for help or share your progress.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Looking back on my browsing history snippets</title>
      <link>https://davidbieber.com/snippets/2020-12-20-looking-back-on-my-browsing-history-snippets/</link>
      <pubDate>Sun, 20 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-12-20-looking-back-on-my-browsing-history-snippets/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;ve now written several snippets about my analyzing my browsing history programmatically. I figured I&amp;rsquo;d collect them all in one place here.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://davidbieber.com/snippets/2019-12-30-analyzing-my-browser-history/&#34;&gt;https://davidbieber.com/snippets/2019-12-30-analyzing-my-browser-history/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://davidbieber.com/snippets/2020-03-19-browsing-history/&#34;&gt;https://davidbieber.com/snippets/2020-03-19-browsing-history/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://davidbieber.com/snippets/2020-04-11-browser-history-queries/&#34;&gt;https://davidbieber.com/snippets/2020-04-11-browser-history-queries/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://davidbieber.com/snippets/2020-04-12-simplifying-sql-with-with/&#34;&gt;https://davidbieber.com/snippets/2020-04-12-simplifying-sql-with-with/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://davidbieber.com/snippets/2020-04-20-browser-history-date-queries/&#34;&gt;https://davidbieber.com/snippets/2020-04-20-browser-history-date-queries/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://davidbieber.com/snippets/2020-04-26-daily-browser-history-summaries/&#34;&gt;https://davidbieber.com/snippets/2020-04-26-daily-browser-history-summaries/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://davidbieber.com/snippets/2020-04-30-detecting-sleeping-hours/&#34;&gt;https://davidbieber.com/snippets/2020-04-30-detecting-sleeping-hours/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://davidbieber.com/snippets/2020-05-15-roaming-the-web/&#34;&gt;https://davidbieber.com/snippets/2020-05-15-roaming-the-web/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Presumably as I write more about this, the list will go out of date. And that&amp;rsquo;s alright. This is just a snippet.&lt;/p&gt;
&lt;p&gt;This motivates me to move all my snippets into Roam Research. I&amp;rsquo;m not going to do this just yet, but it seems a decent idea. Backlinks/tags would then allow for easily keeping an up-to-date list of all the snippets I&amp;rsquo;ve written about various topics.&lt;/p&gt;
&lt;p&gt;Looking back on these many browsing history snippets, what themes stand out? Browser histories are rich with information about our lives. There&amp;rsquo;s a lot we can do to make our lives better using that information.&lt;/p&gt;
&lt;p&gt;We can detect if we&amp;rsquo;re getting distracted, and have automated interventions if we are.&lt;/p&gt;
&lt;p&gt;We can figure out our interests, and notice if they&amp;rsquo;re drifting over time.&lt;/p&gt;
&lt;p&gt;We can reflect on things we&amp;rsquo;ve learned or thought about in the past, revisiting our old ideas. This can help generate new ideas, and also strengthen our memory.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve made some progress on automated distraction detection. I&amp;rsquo;ll have to write a snippet about that soon. I&amp;rsquo;ve also recently poked at getting my browsing history from my phone on my computer, so that can be analyzed in near real-time too. This promises to make distraction detection even more compelling. Very excited to teach Bieber Bot how to stage a distraction intervention some time in the next year.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Derivative of Softmax and the Softmax Cross Entropy Loss</title>
      <link>https://davidbieber.com/snippets/2020-12-12-derivative-of-softmax-and-the-softmax-cross-entropy-loss/</link>
      <pubDate>Sat, 12 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-12-12-derivative-of-softmax-and-the-softmax-cross-entropy-loss/</guid>
      
      <description>&lt;p&gt;Write $y_i = \text{softmax}(\textbf{x})_i = \frac{e^{x_i}}{\sum e^{x_d}}$.&lt;/p&gt;
&lt;p&gt;That is, $\textbf{y}$ is the softmax of $\textbf{x}$. Softmax computes a normalized exponential of its input vector.&lt;/p&gt;
&lt;p&gt;Next write $L = -\sum t_i \ln(y_i)$. This is the softmax cross entropy loss. $t_i$ is a 0/1 target representing whether the correct class is class $i$. We will compute the derivative of $L$ with respect to the inputs to the softmax function $\textbf{x}$.&lt;/p&gt;
&lt;p&gt;We have $\frac{dL}{dx_j} = -\sum t_i \frac{1}{y_i} \frac{dy_i}{d{x_j}}$ from the chain rule.&lt;/p&gt;
&lt;p&gt;We compute $\frac{dy_i}{dx_j}$ using the quotient rule.&lt;/p&gt;
&lt;p&gt;If $i = j$, this gives:&lt;/p&gt;
&lt;p&gt;$\frac{dy_i}{dx_j} = \frac{\sum e^{x_d} \cdot e^{x_i} - e^{x_i} \cdot e^{x_i}}{(\sum e^{x_d})^2}$&lt;/p&gt;
&lt;p&gt;$\frac{dy_i}{dx_j} = \frac{e^{x_i}}{\sum e^{x_d}} \cdot \left(\frac{\sum e^{x_d} - e^{x_i}}{\sum e^{x_d}}\right)$&lt;/p&gt;
&lt;p&gt;$\frac{dy_i}{dx_j} = y_i \cdot (1 - y_i)$&lt;/p&gt;
&lt;p&gt;If $i \ne j$, this gives:&lt;/p&gt;
&lt;p&gt;$\frac{dy_i}{dx_j} = \frac{\sum e^{x_d} \cdot 0 - e^{x_i} \cdot e^{x_j}}{(\sum e^{x_d})^2}$&lt;/p&gt;
&lt;p&gt;$\frac{dy_i}{dx_j} = -\frac{e^{x_i}}{\sum e^{x_d}} \cdot \frac{e^{x_j}}{\sum e^{x_d}} $&lt;/p&gt;
&lt;p&gt;$\frac{dy_i}{dx_j} = -y_i y_j$&lt;/p&gt;
&lt;p&gt;Together these equations give us the derivative of the softmax function:&lt;/p&gt;
&lt;p&gt;$\frac{dy_i}{dx_j} = \begin{cases} y_i \cdot (1 - y_i) &amp;amp; i=j \\\ -y_i y_j &amp;amp; i \ne j \end{cases}$&lt;/p&gt;
&lt;p&gt;Using this result, we can finish computing the derivative of $L$. This gives:&lt;/p&gt;
&lt;p&gt;$\frac{dL}{dx_j} = -\sum t_i \frac{1}{y_i} \frac{dy_i}{d{x_j}} = \sum\limits_i \begin{cases} t_i (y_i - 1) &amp;amp; i=j \\\ t_i y_j &amp;amp; i \ne j \end{cases}$&lt;/p&gt;
&lt;p&gt;Since exactly one of the $t_i$s is 1 and the rest are zeros this further simplifies to:&lt;/p&gt;
&lt;p&gt;$\frac{dL}{dx_j} = y_j - t_j$&lt;/p&gt;
&lt;p&gt;We have computed the derivative of the softmax cross-entropy loss $L$ with respect to the inputs to the softmax function.&lt;/p&gt;
&lt;p&gt;This page is an experiment in publishing directly from Roam Research. &lt;del&gt;It is incomplete, and the formatting is probably all wonky. Bear with me while I get this sorted.&lt;/del&gt; Update (December 13th, 2020): The formatting looks good now!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Brainstorming “Mandatory Reading” for Dodam</title>
      <link>https://davidbieber.com/snippets/2020-12-06-brainstorming-mandatory-reading-for-dodam/</link>
      <pubDate>Sun, 06 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-12-06-brainstorming-mandatory-reading-for-dodam/</guid>
      
      <description>&lt;p&gt;Dodam asked me what ideas I thought were most essential. Here are my first thoughts.&lt;/p&gt;
&lt;h2 id=&#34;idea-programming-literacy&#34;&gt;Idea: Programming literacy&lt;/h2&gt;
&lt;p&gt;Material: COS 126 (for example)&lt;/p&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;p&gt;Understanding the ways in which ideas can be combined is essential for creativity and problem solving. Not being able to see how software can make things possible is a significant setback for this. (Has positives too: constraints beget creativity. This constraint isn’t worth it though!)&lt;/p&gt;
&lt;p&gt;The vast majority of people I interact with have this skillset. So it can be momentarily jarring when it&amp;rsquo;s absent (if it becomes relevant).&lt;/p&gt;
&lt;h2 id=&#34;idea-understanding-other-peoples-limitations&#34;&gt;Idea: Understanding other people’s limitations&lt;/h2&gt;
&lt;p&gt;Material: &lt;a href=&#34;https://xkcd.com/1053/&#34;&gt;https://xkcd.com/1053/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://imgs.xkcd.com/comics/ten_thousand.png&#34; alt=&#34;Ten Thousand&#34;&gt;&lt;/p&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;p&gt;Finding out that someone doesn&amp;rsquo;t know something you expect them to know can be jarring, but being condescending or judgemental in response doesn&amp;rsquo;t help anyone. It&amp;rsquo;s okay to let the person know you&amp;rsquo;re surprised by their lack of knowledge, but best to refrain from adding any negative valence to this surprisal.&lt;/p&gt;
&lt;p&gt;There are essentially no benefits to disrespecting or being incredulous about someone’s limitations in knowledge/skill/memory/etc.&lt;/p&gt;
&lt;p&gt;Everyone learns faster, and everyone finds the world more interesting when these limitations are acknowledged in a supportive way.&lt;/p&gt;
&lt;p&gt;Plus it’s respectful.&lt;/p&gt;
&lt;p&gt;People‘s experiences are varied. Our memories are limited. Our values are different. Let’s help each other to learn and remember, even the most “obvious” of things.&lt;/p&gt;
&lt;h2 id=&#34;idea-super-communication&#34;&gt;Idea: Super-communication&lt;/h2&gt;
&lt;p&gt;Material: Khan Academy blog post from Ben Kamens &lt;a href=&#34;https://bjk5.com/post/71887196490/email-transparency-at-khan-academy#_=_&#34;&gt;https://bjk5.com/post/71887196490/email-transparency-at-khan-academy#_=_&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;p&gt;The people at Khan Academy are incredibly productive (c. 2013). Collectively this group is super talented, driven, and least expectedly: super-communicative.&lt;/p&gt;
&lt;p&gt;The blog post linked above gives a small taste of how.&lt;/p&gt;
&lt;p&gt;My main takeaway from that summer is the value of “super communication”.&lt;/p&gt;
&lt;p&gt;Make every thought, action, idea public to the people it might affect.&lt;/p&gt;
&lt;p&gt;To be clear: They don’t need a notification about every thought; they might never read 90% of them.&lt;/p&gt;
&lt;p&gt;This has a number of positive effects:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Confidence&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let’s say you’re thinking of performing some action, e.g. moving a stack of bricks to where they’ll be used. You think it’s the right thing to do, but you’re not 100% sure. Do you ask someone? Do you do it anyway?&lt;/p&gt;
&lt;p&gt;Under super-communication you don’t ask permission, you instead announce your intent to move the bricks. Then wait a moment before starting to move them to give people a chance to see your message.&lt;/p&gt;
&lt;p&gt;Since all stakeholders have access to this announcement, you can start doing the things you think is right: moving the bricks.&lt;/p&gt;
&lt;p&gt;Someone would let you know if they think you shouldn’t be doing it.&lt;/p&gt;
&lt;p&gt;So through super communication you can take more ownership over construction without worrying about stepping on people’s toes or messing up bigger plans. (To clarify, this strategy requires the broadcasted message to have &lt;strong&gt;some&lt;/strong&gt; visibility, e.g. a low-priority chat room; this doesn&amp;rsquo;t work if no one is going to see the message.)&lt;/p&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Thinking things through&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Super communication is hard work. It’s time consuming to share every thought. But a benefit of this is it makes you concretize your thoughts. Sharing them forces you to put them into words that others can understand. In doing so you naturally think through what others would think of your idea, and so your idea develops and improves.&lt;/p&gt;
&lt;p&gt;You also make yourself open to receiving feedback and thoughts on your idea, which can improve the idea and lead to new ones.&lt;/p&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;Trust and transparency&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Putting your ideas out in the open gives people a better sense of where you&amp;rsquo;re coming from, and what your intentions are. It builds trust, and prevents misunderstandings about who is doing what and when.&lt;/p&gt;
&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;No surprises&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You&amp;rsquo;ll avoid having situations where person A thought person B was working on X is person B has actively been communicating that they&amp;rsquo;re working on Y.&lt;/p&gt;
&lt;p&gt;Super communication is hard work. I fall out of the habit quickly. But every time I’m reminded of its value and my experience at Khan Academy I’m reinforced in my belief that is worth striving for, and at least for a short time I’m better for it.&lt;/p&gt;
&lt;h2 id=&#34;idea-communication-bubblesbonding-and-bridging&#34;&gt;Idea: Communication bubbles/bonding and bridging&lt;/h2&gt;
&lt;p&gt;Material: Maybe start with &lt;a href=&#34;https://ncase.me/crowds/&#34;&gt;https://ncase.me/crowds/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;tl;dr: &amp;ldquo;A healthy society needs a sweet spot of bonds within groups and bridges between groups.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Nicky Case links to more substantive material if you want to dive deeper. The idea itself is simple though; it’s being actively conscious of it that’s important and which can be challenging.&lt;/p&gt;
&lt;h2 id=&#34;idea-castles-in-the-clouds-as-belief-systems&#34;&gt;Idea: Castles in the clouds as belief systems&lt;/h2&gt;
&lt;p&gt;The core idea is that all beliefs have provenance, but the provenance can be lost while the beliefs remain.&lt;/p&gt;
&lt;p&gt;I don’t have a good source for this one, but I think it’s essential.&lt;/p&gt;
&lt;p&gt;Ironic, eh?&lt;/p&gt;
&lt;p&gt;I’ll elaborate more on this idea later.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>4.2e-8 of All of Human Experience</title>
      <link>https://davidbieber.com/snippets/2020-12-03-4.2e-8-of-all-of-human-experience/</link>
      <pubDate>Thu, 03 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-12-03-4.2e-8-of-all-of-human-experience/</guid>
      
      <description>&lt;p&gt;About 107 billion people have &lt;em&gt;ever&lt;/em&gt; lived.&lt;/p&gt;
&lt;p&gt;Across all time, the average life expectancy of a person is just under 30 years.&lt;/p&gt;
&lt;p&gt;So, there have only been 3.21 trillion person-years experienced. Total.&lt;/p&gt;
&lt;p&gt;7.8 billion people are alive today.&lt;/p&gt;
&lt;p&gt;The average age globally is about 30 years.&lt;/p&gt;
&lt;p&gt;So living people today collectively hold about 234 billion years of experience.&lt;/p&gt;
&lt;p&gt;That means that a little &lt;strong&gt;over 7% of all human experience is held by living people&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;One day spent alone constitutes 8.5e-16 of all of human experience. A month is 2.6e-14 of all of human experience.&lt;/p&gt;
&lt;p&gt;A year spent with a partner is 6.2e-13 of all of human experience.&lt;/p&gt;
&lt;p&gt;Four years spent with 1500 other students is 1.9e-9 of all of human experience.&lt;/p&gt;
&lt;p&gt;By a crude estimate, a whopping 4.2e-8 of all human experience was spent watching Game of Thrones. Humanity will never get that time back.&lt;/p&gt;
&lt;p&gt;These are small numbers, but not &lt;strong&gt;that&lt;/strong&gt; small. Thinking that my graduating class alone (not even counting the people a year above or below me) holds nearly 2e-9 of all human experience from our four years together is kind of mind-bending.&lt;/p&gt;
&lt;p&gt;For comparison, let&amp;rsquo;s imagine that the surface of Earth represents all of human experience. Then 4.2e-8 of human experience (the amount dedicated to watching Game of Thrones) is represented by 8.3 square miles.&lt;/p&gt;
&lt;p&gt;The 6.2e-13 of human experience held by you and your partner quarantining for a year? That&amp;rsquo;s over 3400 square feet. And a whole lifetime (est. 80 years) covers 3.141 acres.&lt;/p&gt;
&lt;p&gt;These are not at all negligible!&lt;/p&gt;
&lt;p&gt;All of this is to say: let&amp;rsquo;s treasure our existence, and let&amp;rsquo;s also not discount its significance.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Supervisord</title>
      <link>https://davidbieber.com/snippets/2020-12-02-supervisord/</link>
      <pubDate>Wed, 02 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-12-02-supervisord/</guid>
      
      <description>&lt;p&gt;Supervisord has been the single best quality-of-life improvement for software development for me in 2020.&lt;/p&gt;
&lt;p&gt;Many thanks to 
&lt;a href=&#34;https://vikb.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Vik Bhandari&lt;/a&gt; for suggesting that I use it.&lt;/p&gt;
&lt;p&gt;What is supervisord? It&amp;rsquo;s a &amp;ldquo;process control system,&amp;rdquo; meaning that it&amp;rsquo;s software that starts, stops, and monitors other software that you want to run.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example. Let&amp;rsquo;s say you have a program &lt;code&gt;check_for_sales&lt;/code&gt; that periodically pings Amazon looking for sales on that new shoe-phone you&amp;rsquo;ve had your eye on. When it notices a drop in prices, it sends you a text.&lt;/p&gt;
&lt;p&gt;Without supervisord, you might start the program, and find the next day that it has hit an error (maybe one of the requests to Amazon timed out in a way you weren&amp;rsquo;t anticipating), the program terminated, and the item sold out while you weren&amp;rsquo;t looking!&lt;/p&gt;
&lt;p&gt;With supervisord, you can have &lt;code&gt;check_for_sales&lt;/code&gt; automatically restart on failure. Supervisord will notice the failure, and restart the program for you.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been using supervisord for all sorts of things, like monitoring Bieber Bot for new messages, keeping my website&amp;rsquo;s development server live, automatically posting snippets from Roam (like this one), and auto-processing screenshots and screen recordings that I take. I have 15 processes monitored by supervisord in total across a number of side projects.&lt;/p&gt;
&lt;p&gt;Before supervisord, I had half the number of processes always-on in the background on my computer. I would keep extra terminal windows open to keep them running. And restarting my computer was a pain because I had to bring up these processes one at a time.&lt;/p&gt;
&lt;p&gt;Now, with supervisord, restarting my machine is no big deal. This let&amp;rsquo;s me use my computer more freely, and I feel much less hesitation in starting a new project that requires having an always-on process.&lt;/p&gt;
&lt;p&gt;You can learn more about supervisord from their website 
&lt;a href=&#34;http://supervisord.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;supervisord.org&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Updating Google Slides through Roam Research</title>
      <link>https://davidbieber.com/snippets/2020-11-30-updating-google-slides-through-roam-research/</link>
      <pubDate>Mon, 30 Nov 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-11-30-updating-google-slides-through-roam-research/</guid>
      
      <description>&lt;p&gt;Check out this &amp;ldquo;demo video&amp;rdquo; I made! It shows me making a presentation using Roam Research references. When I update the block in Roam that I&amp;rsquo;m referencing, the presentation gets updated automatically.&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/YccjrI3fmhc&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;Editing slides and docs in this way would be so useful! Being able to focus on content in Roam, and presentation in a tool that&amp;rsquo;s built for presentation (like Docs and Slides) would be such a powerful combination.&lt;/p&gt;
&lt;p&gt;In my experience, Roam is a powerful tool for &lt;strong&gt;thinking&lt;/strong&gt; and &lt;strong&gt;note-taking&lt;/strong&gt;, but not as useful for sharing those thoughts. When you&amp;rsquo;re sharing, you want to tell a story. You want to guide the reader through your thought process, and be in control of the narrative the whole time.&lt;/p&gt;
&lt;p&gt;With Roam, the reader might wander off down some unexpected path you, the writer, weren&amp;rsquo;t anticipating. Once that happens, you&amp;rsquo;ve lost the reader. They&amp;rsquo;re going to find themselves in unpolished not-really-relevant material, and you&amp;rsquo;re not going to get to convey the narrative you were aiming for.&lt;/p&gt;
&lt;p&gt;This is fine for an 
&lt;a href=&#34;http://en.wikipedia.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;encyclopedia&lt;/a&gt;, but not so good for telling a story.&lt;/p&gt;
&lt;p&gt;Being able to seamlessly do your thinking in Roam while also producing polished presentations (not just Slides, but anything meant for sharing, like emails, documents, images, etc) will be an absolute game changer for how we think and communicate.&lt;/p&gt;
&lt;p&gt;This video may not be a real product, but it represents a real vision, and we have the technology to make it real. Now, let&amp;rsquo;s put in the work and bring this vision into reality.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll post more in future snippets about how I think we can build a system like this today. (And I&amp;rsquo;ll also share how I made the video, despite the product integration not having been developed yet.)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Publishing Through Roam Research</title>
      <link>https://davidbieber.com/snippets/2020-11-24-publishing-through-roam-research/</link>
      <pubDate>Tue, 24 Nov 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-11-24-publishing-through-roam-research/</guid>
      
      <description>&lt;p&gt;With this snippet I&amp;rsquo;m testing out a new snippet publishing system: publishing snippets directly from Roam Research. Using the system is simple: I simply tag any bullet with &amp;ldquo;ok-to-publish&amp;rdquo; and Bieber Bot publishes it and its children as a snippet.&lt;/p&gt;
&lt;p&gt;Why another way of writing snippets? I&amp;rsquo;ve been writing quite a bit in Roam lately but I haven&amp;rsquo;t been publishing snippets lately. In truth, this new publishing mechanism is more a novelty than something practically useful. It would be easy enough to copy a snippet out of Roam into a text editor or to Bieber Bot in Facebook Messenger to publish it.&lt;/p&gt;
&lt;p&gt;It certainly is appealing to be able to publish directly in Roam where I spend a lot of my time writing though. I think being able to publish directly from Roam may appeal to many other people as well.&lt;/p&gt;
&lt;p&gt;The place where it may save time is in making changes to snippets. If I write a snippet in Roam today and publish it in the usual way, any changes I make it Roam aren’t reflected in the published version. Under this new system the copy on my website can automatically be updated to match the copy in Roam whenever I make changes there.&lt;/p&gt;
&lt;p&gt;Anyway, I&amp;rsquo;ve marked this snippet as ok-to-publish, so once I build the system this should show up on my website. If you&amp;rsquo;re reading this there, it worked!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Letting Adriana put things in my Leitner Box</title>
      <link>https://davidbieber.com/snippets/2020-11-07-letting-adriana-put-things-in-my-leitner-box/</link>
      <pubDate>Sat, 07 Nov 2020 08:14:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-11-07-letting-adriana-put-things-in-my-leitner-box/</guid>
      
      <description>&lt;p&gt;I’ve been using spaced repetition for 2-3 weeks now. I’m not using Anki or any of the prebuilt systems that track your queue of items for you. Instead, I’m keeping the things I want to study in Roam Research and using a make-shift system of tags and Browserflow Flows to make the spaced repetition system relatively frictionless.&lt;/p&gt;
&lt;p&gt;I’ll save the details of the system for another snippet. Today, I just want to jot down the idea of allowing Adriana (through the use of Bieber Bot) to add items to my spaced repetition system.&lt;/p&gt;
&lt;p&gt;The idea is relatively simple, but it does involve one new component that may be tricky to implement robustly. Under this idea, Adriana would be able to send Bieber Bot a message saying e.g. “help David to learn the names of the planets” and a card would be added to my spaced repetition system saying “learn the names of the planets. -Adriana”. I could then split this card into multiple cards as I usually do when I encounter a card with too much content simultaneously, or Adriana could have Bieber Bot add smaller cards one at a time.&lt;/p&gt;
&lt;p&gt;The new component that would be necessary is giving Bieber Bot edit access to my Roam Research database. Currently he has delayed read access through Roam-to-Git, but giving him write access might mean teaching him how to use Roam in a (headless, most likely) browser. Nothing he can’t handle, but it would increase the amount of time needed to get this system up and running.&lt;/p&gt;
&lt;p&gt;Once Adriana (or any of Bieber Bot’s friends) can add cards into my spaced repetition system, this can be a fun way to learn about new topics and share new ideas.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Extracting Snippets from Roam Research</title>
      <link>https://davidbieber.com/snippets/2020-11-03-extracting-snippets-from-roam-research/</link>
      <pubDate>Tue, 03 Nov 2020 15:22:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-11-03-extracting-snippets-from-roam-research/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;ve been writing a lot these days inside of Roam Research. I wonder if there&amp;rsquo;s a good way to identify snippet-quality items from within my Roam database.&lt;/p&gt;
&lt;p&gt;One option would be to pick out decent-sized sections of continuous text.
If I&amp;rsquo;m taking notes in a bunch of different areas, that&amp;rsquo;s probably not well suited for publishing as a snippet unless I were to clean it up first.
But if I see there&amp;rsquo;s a large chunk of text that&amp;rsquo;s been added in a contiguous block, there&amp;rsquo;s a decent chance that its snippet-quality.
&amp;ldquo;Snippet-quality&amp;rdquo; isn&amp;rsquo;t a particularly high bar. The bar is really just that we&amp;rsquo;d want text that forms a coherent thought rather than being a few lines on totally unrelated thoughts (which can also appear contiguously in Roam).&lt;/p&gt;
&lt;p&gt;A few days ago I set up Roam-to-Git, so every hour my Roam database is backed up to a private GitHub repository. It would be easy enough to look through the git diffs to see if there&amp;rsquo;s something that fits this description.
One possible issue with this though is that the backup script doesn&amp;rsquo;t know if I&amp;rsquo;m in the middle of writing. So it&amp;rsquo;s possible it will catch me mid-snippet.
Perhaps if I look at the diff between head and two commits back, I can avoid missing snippets that got split over multiple commits. It&amp;rsquo;s an idea worth looking in to, though the number of false positives might be too high without a fair amount of tuning.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Questions to Answer About Python Fire</title>
      <link>https://davidbieber.com/snippets/2020-10-22-questions-to-answer-about-python-fire/</link>
      <pubDate>Thu, 22 Oct 2020 20:31:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-10-22-questions-to-answer-about-python-fire/</guid>
      
      <description>&lt;p&gt;Tomorrow I&amp;rsquo;m giving a talk to Women Who Code on Python Fire. Python Fire is a Python library I wrote back in 2017 that makes command line interfaces automatically out of any Python object you give it.&lt;/p&gt;
&lt;p&gt;I have my talk planned but there are a few pieces of the story I haven&amp;rsquo;t included in my talk yet. They are 1) Why did I build Python Fire? 2) How are people using Python Fire in the real world? 3) What&amp;rsquo;s it like maintaining an open source project?&lt;/p&gt;
&lt;p&gt;To the first question, I should explain how we used Boom at Nest. Boom was the proto-version of Fire that inspired Fire&amp;rsquo;s development. At Nest we had an ETL pipeline consisting of several distributed systems. For example data would pass through SQS, Kafka, Storm, and Pentaho while it was being ingested. We wanted to write tests for this complex series of systems. And we also wanted to be able to manually operate the systems. So we wrote Python functions for controlling each part of the system.&lt;/p&gt;
&lt;p&gt;Using Python&amp;rsquo;s inspect feature we then turned this collection of functions automatically into a CLI. This allowed us to reuse the same code both for writing tests and for giving the operators control over the ingestion pipelines without needing to do duplicate work. This was the inspiration for Fire.&lt;/p&gt;
&lt;p&gt;To question two: there are thousands of uses of Fire on GitHub. OkCupid uses it for data analysis. One person I corresponded with uses Fire to control after market engines. About 10% of uses on GitHub are for machine learning projects, including the GPT codebase. There are also a couple hundred uses within Google too, though gflags (aka abseil) is the Google standard for CLIs still.&lt;/p&gt;
&lt;p&gt;And finally to question three, it&amp;rsquo;s really nice to be appreciated! I built Fire to scratch my own itch from working at Nest and Google, but after releasing Fire it&amp;rsquo;s gotten quite popular. Over 17k stars on GitHub, thousands of open source projects using it, and over ten million installs from every country around the world. It&amp;rsquo;s really nice to see my effort appreciated.&lt;/p&gt;
&lt;p&gt;My favorite is that someone has written a blog post explaining why Fire is a good tool for teaching Python, because it lets the beginner start programming without needing to understand any boilerplate. I&amp;rsquo;m hopeful that Fire is indeed helping people learn to program.&lt;/p&gt;
&lt;p&gt;Time permitting I will add these questions and answers to my talk tomorrow.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>An Update on my 2020 Resolution</title>
      <link>https://davidbieber.com/snippets/2020-10-09-an-update-on-my-2020-resolution/</link>
      <pubDate>Fri, 09 Oct 2020 22:55:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-10-09-an-update-on-my-2020-resolution/</guid>
      
      <description>&lt;p&gt;My goal for this year was to get good at communicating publicly. I decided to measure progress in terms of the number of times I communicated publicly. 100 public communications was the goal. Where am I today?&lt;/p&gt;
&lt;p&gt;This is my 42nd snippet for the year. I&amp;rsquo;m giving a talk on Python Fire publicly next week. I published 4 papers (
&lt;a href=&#34;https://arxiv.org/abs/2010.12621&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;IPA-GNN&lt;/a&gt;, 
&lt;a href=&#34;https://arxiv.org/abs/2003.09040&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;TF-Coder&lt;/a&gt;, 
&lt;a href=&#34;https://arxiv.org/abs/2002.09067&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Unique Randomizer&lt;/a&gt;, and 
&lt;a href=&#34;https://arxiv.org/abs/2007.14381&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;BUSTLE&lt;/a&gt;). So far two of them have been accompanied by open source releases (update: now three!).&lt;/p&gt;
&lt;p&gt;Add in a handful of paper presentations and Google-internal talks, and its safe to say I&amp;rsquo;m past the half-way point toward the goal. Only trouble is we&amp;rsquo;re over 75% of the way through the year. I&amp;rsquo;d better get communicating!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Biking in the Morning</title>
      <link>https://davidbieber.com/snippets/2020-10-08-biking-in-the-morning/</link>
      <pubDate>Thu, 08 Oct 2020 22:04:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-10-08-biking-in-the-morning/</guid>
      
      <description>&lt;p&gt;Some of the 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-10-06-the-snippets-i-dont-publish/&#34;&gt;snippets I did not publish&lt;/a&gt; were about my plans for biking in the morning. For the last several days I&amp;rsquo;ve been biking to East Rock each morning, doing so before starting work on work days. I bring my pocket-sized keyboard and my phone, and when I&amp;rsquo;m at the top of the Rock I use my friend Jacob Cole&amp;rsquo;s app, ThoughtStream, to write about whatever&amp;rsquo;s on my mind. Sometimes this is a potential snippet, and sometimes it&amp;rsquo;s just planning for the day.&lt;/p&gt;
&lt;p&gt;I really like this routine but I&amp;rsquo;m not confident that I&amp;rsquo;ll continue it. Consistently getting up early for an extended period of time can be challenging, and I&amp;rsquo;m not inclined to set an alarm to help. Also, the weather is getting cooler.&lt;/p&gt;
&lt;p&gt;I certainly hope that I continue this routine, and I intend to maintain it. I simply don&amp;rsquo;t know that I will, and don&amp;rsquo;t feel confidently enough that I will to make any sort of declaration or commitment to doing so. Is there a name for this type of goal? I think &amp;ldquo;intent&amp;rdquo; is appropriate, but doesn&amp;rsquo;t capture the aspirational aspect of it. For now lets call it an &amp;ldquo;aspirational intent&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;I aspirationally intend to keep biking to East Rock most mornings, until the weather gets too cold to permit doing so.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Introducing the Snippet Queue</title>
      <link>https://davidbieber.com/snippets/2020-10-06-introducing-the-snippet-queue/</link>
      <pubDate>Tue, 06 Oct 2020 22:16:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-10-06-introducing-the-snippet-queue/</guid>
      
      <description>&lt;p&gt;This is my first snippet published using my 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-10-06-further-reducing-the-publication-barrier-with-queuing/&#34;&gt;snippet queue idea&lt;/a&gt;. If all goes well, it will be (read: was) published tomorrow evening (October 7, 2020).&lt;/p&gt;
&lt;p&gt;The system works like this. I store a queue of snippets in Redis. Each snippet has the title, content, and date associated with it, as well as an id number. I can have Bieber Bot enqueue a new snippet by messaging him with &amp;ldquo;Queue snippet!&amp;rdquo; and the snippet details. He also responds to queries to update, view, or remove an existing snippet, or to view the current queue of snippets.&lt;/p&gt;
&lt;p&gt;Then, every evening Bieber Bot looks at the oldest item in the queue. If he&amp;rsquo;s already asked me about it, and I haven&amp;rsquo;t told him not to publish it, he goes and publishes it to my website. If he hasn&amp;rsquo;t asked me about it yet, he asks me if its OK to publish. As long as I don&amp;rsquo;t say no and remove the snippet from the queue, Bieber Bot will go forward with publishing the snippet the next day.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Further Reducing the Publication Barrier with Queuing</title>
      <link>https://davidbieber.com/snippets/2020-10-06-further-reducing-the-publication-barrier-with-queuing/</link>
      <pubDate>Tue, 06 Oct 2020 13:29:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-10-06-further-reducing-the-publication-barrier-with-queuing/</guid>
      
      <description>&lt;p&gt;What is the barrier to publication? It&amp;rsquo;s first and foremost a mental barrier. Sure, the act of writing presents its own challenges, but for me the mental hurdle of clicking send can be significant. Snippets lowers the barrier substantially compared with social media, messaging individuals, or even traditional blogging. Still, there&amp;rsquo;s room to lower the barrier even more; e.g. private journaling and &lt;em&gt;thinking&lt;/em&gt; itself have much lower barriers than Snippets does.&lt;/p&gt;
&lt;p&gt;The idea today for lowering the barrier is a publication queue. In this idea, I write a snippet, send it to Bieber Bot, and he holds on to it for a bit. Then, after a day or so, he lets me know that he&amp;rsquo;s going to publish it soon. He gives me an opportunity to tell him not to publish it, but after some time has passed, he goes ahead and publishes it in my Snippets section on my behalf.&lt;/p&gt;
&lt;p&gt;During that waiting period, I can send Bieber Bot revised versions of the Snippet, which will supersede the original. This way, when I send Bieber Bot the original snippet, I do so knowing that it will only be published as is if 1) I don&amp;rsquo;t come up with a way to improve it and 2) I don&amp;rsquo;t decide not to publish it. This takes a bit of the decision making burden off of present-David, and gives it to future-David. Between the two of them, they should be able to handle the publication no problem.&lt;/p&gt;
&lt;p&gt;This idea acts similarly to GMail&amp;rsquo;s &amp;ldquo;send later&amp;rdquo; feature, but without the need to choose a send time. Clicking &amp;ldquo;send later&amp;rdquo; is easier than clicking &amp;ldquo;send&amp;rdquo; because there&amp;rsquo;s an opportunity to undo or make changes.&lt;/p&gt;
&lt;p&gt;In addition to decreasing the barrier to publication, one thing I like about this idea is that it gives me an opportunity to revisit old ideas. When Bieber Bot tells me &amp;ldquo;Hey, last chance to rescind publication of this Snippet&amp;rdquo; that gives me an opportunity to reflect on what I&amp;rsquo;d written.&lt;/p&gt;
&lt;p&gt;I also like that it can spread out the publication of snippets that I write in a single sitting. Currently, after publishing a single snippet, I&amp;rsquo;m not inclined to write more because I would feel funny publishing multiple snippets in quick succession (another mental barrier to climb over, I suppose). If I knew that Bieber Bot would take care of spacing out the publications, I might feel more comfortable writing a second or third snippet in a single sitting. I&amp;rsquo;d like that.&lt;/p&gt;
&lt;p&gt;So, a publication queue it is! This shouldn&amp;rsquo;t be too much effort to implement given the work I&amp;rsquo;ve already done to support snippet publications, scheduling, question-asking, and messaging in Bieber Bot.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The Snippets I Don&#39;t Publish</title>
      <link>https://davidbieber.com/snippets/2020-10-06-the-snippets-i-dont-publish/</link>
      <pubDate>Tue, 06 Oct 2020 12:33:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-10-06-the-snippets-i-dont-publish/</guid>
      
      <description>&lt;p&gt;The goal of Snippets is to minimize the barrier to writing as much as possible. To this end, it has been very effective. Still, there are several snippets that I write and do not publish, despite my self-insistence that the barrier to publication be minimal.&lt;/p&gt;
&lt;p&gt;What don&amp;rsquo;t I publish, and why? Looking over my recent unpublished snippets, some themes appear. Here&amp;rsquo;s what I don&amp;rsquo;t tend to publish:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Work related snippets&lt;/li&gt;
&lt;li&gt;Ideas that trail off mid thought&lt;/li&gt;
&lt;li&gt;Status update + planning snippets&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I tend not to post work related snippets just to be on the safe side with respect to Google confidentiality, though I&amp;rsquo;m confident the snippets I&amp;rsquo;m writing would be OK to publish if I requested permission to do so (of course, that would raise the barrier to publishing significantly which defeats the purpose of snippets.)&lt;/p&gt;
&lt;p&gt;This has a cascading effect though, because now when I write a status update or planning snippet, it references things I&amp;rsquo;ve written in unpublished snippets. Such a snippet wouldn&amp;rsquo;t stand alone effectively. I suppose that&amp;rsquo;s not such a problem though; if I ever post a snippet mentioning in-progress projects, feel free to ask me about them, or feel free to ignore. The main audience of the snippet is probably me.&lt;/p&gt;
&lt;p&gt;In brief, the recent snippets I did not publish are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A follow up to the &amp;ldquo;Infinite Distractions&amp;rdquo; plan&lt;/li&gt;
&lt;li&gt;Considering discrete vs fuzzy decision making&lt;/li&gt;
&lt;li&gt;Several activities I&amp;rsquo;d like to do more of, and strategies to help me to do them&lt;/li&gt;
&lt;li&gt;A plan for biking the next day&lt;/li&gt;
&lt;li&gt;An idea for how to teach Bieber Bot to ask and answer questions&lt;/li&gt;
&lt;li&gt;Reflecting, work planning, and more Bieber Bot interaction planning&lt;/li&gt;
&lt;li&gt;Some reflecting and daily planning (half work-related) from yesterday&lt;/li&gt;
&lt;li&gt;A 4-line idea for queuing publication of snippets&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Perhaps I&amp;rsquo;ll put a few of these up. I would, after all, like to get better at communicating publicly.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Checking Your Fan Speed and CPU Temperature on Mac OS (2020)</title>
      <link>https://davidbieber.com/snippets/2020-10-03-checking-your-fan-speed-and-cpu-temperature-on-mac-os/</link>
      <pubDate>Sat, 03 Oct 2020 15:46:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-10-03-checking-your-fan-speed-and-cpu-temperature-on-mac-os/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;ve seen people monitor their CPU temperature and today my laptop was running hot, so I wanted to do so myself. Googling &amp;ldquo;check laptop temperature mac&amp;rdquo; gives projects you can download. I didn&amp;rsquo;t want to have to trust someone else&amp;rsquo;s tool or mess around with someone else&amp;rsquo;s code, and I knew there must be a system call that gives me sensor stats, so I kept looking.&lt;/p&gt;
&lt;p&gt;Indeed, there&amp;rsquo;s a command you can run to get your processor temperatures and fan speeds.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sudo powermetrics --samplers smc&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;To narrow down the stats you see further, you can grep for e.g. &amp;ldquo;Fan:&amp;rdquo;, &amp;ldquo;CPU die temperature:&amp;rdquo;, or &amp;ldquo;GPU die temperature:&amp;rdquo;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;sudo powermetrics --samplers smc | grep &amp;quot;Fan:&amp;quot;
sudo powermetrics --samplers smc | grep &amp;quot;CPU die temperature:&amp;quot;
sudo powermetrics --samplers smc | grep &amp;quot;GPU die temperature:&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Use egrep if you want all three:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;sudo powermetrics --samplers smc | egrep &#39;temp|Fan&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, why does 
&lt;a href=&#34;https://www.mmhmm.app/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;mmhmm&lt;/a&gt; make my machine run so hot?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Infinite Distractions and Getting a Good Sear</title>
      <link>https://davidbieber.com/snippets/2020-10-01-infinite-distractions-and-getting-a-good-sear/</link>
      <pubDate>Thu, 01 Oct 2020 10:54:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-10-01-infinite-distractions-and-getting-a-good-sear/</guid>
      
      <description>&lt;p&gt;These days I have six &amp;ldquo;infinite distractions&amp;rdquo; — things I do mindlessly that are roughly limitless in content. They are: YouTube, YCombinator News, Google News, Reddit, Facebook, and Twitter.&lt;/p&gt;
&lt;p&gt;Some of these are new additions to my repertoire, added I expect in response to my efforts to suppress viewing the others.
I&amp;rsquo;m going to try a strategy of writing down the distraction rather than attending to it whenever I am drawn to it. Additionally, when my brain craves something like this, I&amp;rsquo;m going to make an effort to do one of the following instead: reaching out to to a friend, or going down the rabbit hole on a particular topic.&lt;/p&gt;
&lt;p&gt;The former is just healthy. The latter I think satisfies the same brain cravings as e.g. mindless going on YouTube. But by selecting the topic to dive into deliberately rather than letting the whims of the YouTube/Reddit/etc algorithm select the content for me, I expect a few benefits. I expect the time will feel more valuable to me after the fact, I&amp;rsquo;ll learn something I care about, and I will remember better what I learned because it will be more connected to itself and my interests, I hope.&lt;/p&gt;
&lt;p&gt;I tried this last night and learned about how to get a good sear (in brief: dry the protein, let it cool if it just cooked, and don’t move it around while searing).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Why Phone Snippets (A Test Phone Snippet)</title>
      <link>https://davidbieber.com/snippets/2020-09-27-why-phone-snippets-a-test-phone-snippet/</link>
      <pubDate>Sun, 27 Sep 2020 16:49:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-09-27-why-phone-snippets-a-test-phone-snippet/</guid>
      
      <description>&lt;p&gt;Why do I want to be able to post snippets from my phone?
I enjoy hiking or biking somewhere pleasant, bringing a pocket-sized Bluetooth keyboard, and writing on my phone.&lt;/p&gt;
&lt;p&gt;If you’re seeing this snippet (which you are), that means not only does posting snippets through Bieber Bot work, editing them though Bieber Bot does too.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Posting Snippets from My Phone</title>
      <link>https://davidbieber.com/snippets/2020-09-27-posting-snippets-from-my-phone/</link>
      <pubDate>Sun, 27 Sep 2020 16:32:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-09-27-posting-snippets-from-my-phone/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;d like to be able to post snippets from my phone.
As I&amp;rsquo;ve stated before, the purpose of the snippets section of my website is to lower the barrier to me publishing as much as possible.
Being able to post a snippet from my phone would help in this respect.&lt;/p&gt;
&lt;p&gt;This doesn&amp;rsquo;t seem so hard to set up, especially now that Bieber Bot runs continuously on my laptop.
I could have Bieber Bot listen for a message like:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-md&#34;&gt;Snippet!
Posting Snippets from My Phone
I&#39;d like to be able to post...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When he receives such a message, what should he do?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a new file with the appropriate front matter and content.&lt;/li&gt;
&lt;li&gt;Commit that file and push it to GitHub.&lt;/li&gt;
&lt;li&gt;Run the ansible update script.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That&amp;rsquo;s it. This MVP should be relatively easy to get up and running.&lt;/p&gt;
&lt;p&gt;Update: It is indeed up and running now. I wrote this snippet on my phone :).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Writing with GPT-3</title>
      <link>https://davidbieber.com/snippets/2020-07-22-writing-with-gpt3/</link>
      <pubDate>Wed, 22 Jul 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-07-22-writing-with-gpt3/</guid>
      
      <description>&lt;p&gt;GPT-3 is a language model developed at Open AI, and I&amp;rsquo;ve been having a lot of fun playing with it. In fact, I&amp;rsquo;ve written this post in collaboration with GPT-3. See if you can spot which parts are written by me and which parts come from GPT-3.&lt;/p&gt;
&lt;h2 id=&#34;part-1-brainstorming&#34;&gt;Part 1: Brainstorming&lt;/h2&gt;
&lt;p&gt;The first thing I did when I got access to GPT-3 is use it to brainstorm uses for GPT-3. I gave it these 5 ideas:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Explain mathematics more simply (why is X true?)&lt;/li&gt;
&lt;li&gt;Generate programs from input/output examples&lt;/li&gt;
&lt;li&gt;Generate questions about a paper I read&lt;/li&gt;
&lt;li&gt;Create a list of machine translation tips and tricks&lt;/li&gt;
&lt;li&gt;Create an adventure game&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And it came back with 15 more:&lt;/p&gt;
&lt;ol start=&#34;6&#34;&gt;
&lt;li&gt;Create a list of Tor commands to run to defend against an attack&lt;/li&gt;
&lt;li&gt;Create a cheat sheet for screenwriters&lt;/li&gt;
&lt;li&gt;Generate advice for a scene&lt;/li&gt;
&lt;li&gt;Generate XKCD comics&lt;/li&gt;
&lt;li&gt;Create a crib sheet for an arbitrary Python API&lt;/li&gt;
&lt;li&gt;Make a list of movies to watch&lt;/li&gt;
&lt;li&gt;Make a list of scholarly algorithms/heuristics worth reading&lt;/li&gt;
&lt;li&gt;Make a list of generic questions about Pedagogy&lt;/li&gt;
&lt;li&gt;Make a list of cognitive exercises&lt;/li&gt;
&lt;li&gt;Show patterns generated by awesome people&lt;/li&gt;
&lt;li&gt;Generate small cooking tasks&lt;/li&gt;
&lt;li&gt;Generate characters for a project&lt;/li&gt;
&lt;li&gt;Generate configuration options&lt;/li&gt;
&lt;li&gt;Generate flashcards&lt;/li&gt;
&lt;li&gt;Organize my computer/files&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And then 15 more:&lt;/p&gt;
&lt;ol start=&#34;6&#34;&gt;
&lt;li&gt;Explain things to my parents via messenger&lt;/li&gt;
&lt;li&gt;Explain things to my children via messenger&lt;/li&gt;
&lt;li&gt;Explain mathematical algorithms&lt;/li&gt;
&lt;li&gt;Automated interface design&lt;/li&gt;
&lt;li&gt;Mechanize a Nagihara Kan Airlines website&lt;/li&gt;
&lt;li&gt;Clickbait generator&lt;/li&gt;
&lt;li&gt;Music description (Herbie Hancock is playing &amp;ldquo;Dolphin Dance&amp;rdquo; live in London on the 18th March 1968)&lt;/li&gt;
&lt;li&gt;Tell me not to waste my time looking at x&lt;/li&gt;
&lt;li&gt;Interesting facts about Wikipedia&lt;/li&gt;
&lt;li&gt;Explain something to someone while my attention is elsewhere&lt;/li&gt;
&lt;li&gt;Detect adverts in x&lt;/li&gt;
&lt;li&gt;Image caption/caption game&lt;/li&gt;
&lt;li&gt;Speculate about the true utility function of x&lt;/li&gt;
&lt;li&gt;Auto-generate tests for a program&lt;/li&gt;
&lt;li&gt;Explain why my code is currently failing tests.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And then 15 more:&lt;/p&gt;
&lt;ol start=&#34;6&#34;&gt;
&lt;li&gt;Generate plots or character/story summaries&lt;/li&gt;
&lt;li&gt;Generate legal examples&lt;/li&gt;
&lt;li&gt;Generate words for crosswords&lt;/li&gt;
&lt;li&gt;Check my grammar&lt;/li&gt;
&lt;li&gt;Supply filler text for themed writing (horror, sci-fi etc.)&lt;/li&gt;
&lt;li&gt;Explain why an AI can&amp;rsquo;t read (can it comprehend metaphors?)&lt;/li&gt;
&lt;li&gt;Provide entertaining answers to obscure questions&lt;/li&gt;
&lt;li&gt;Get writing ideas and generate word combinations&lt;/li&gt;
&lt;li&gt;Create background for an NPC I need for a D&amp;amp;D game&lt;/li&gt;
&lt;li&gt;Help a sick writer generate plots&lt;/li&gt;
&lt;li&gt;Input pre-generated (from books etc.) phrases and use them for literary analysis&lt;/li&gt;
&lt;li&gt;Help explain a mathematical proof&lt;/li&gt;
&lt;li&gt;Develop a game/story/character I need&lt;/li&gt;
&lt;li&gt;Make short stories I can &amp;ldquo;overlay&amp;rdquo; on a fictional Universe I&amp;rsquo;ve created (ala Ready Player One)&lt;/li&gt;
&lt;li&gt;Make a short film/audio drama&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;What a lovely list of lists of ideas! I wonder how many of these ideas are novel.&lt;/p&gt;
&lt;p&gt;Some of these ideas are outside the scope of what GPT-3 can do. For example, generating XKCD comics seems too difficult. Others are duplicates, such as &amp;ldquo;Explain mathematical algorithms&amp;rdquo; (duplicate of &amp;ldquo;Explain mathematics more simply&amp;rdquo;). And still others don&amp;rsquo;t make sense &amp;ndash; &amp;ldquo;Mechanize a Nagihara Kan Airlines website&amp;rdquo;? Overall though, solid set of ideas.&lt;/p&gt;
&lt;h2 id=&#34;part-2-mathematics&#34;&gt;Part 2: Mathematics&lt;/h2&gt;
&lt;p&gt;Once I&amp;rsquo;d gotten GPT-3 to do some brainstorming, I realized I&amp;rsquo;d need to test its capabilities before trying its suggestions out in earnest.&lt;/p&gt;
&lt;p&gt;I taught it how to evaluate simple expressions and take derivatives.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the first prompt I used:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-md&#34;&gt;Question: f(x) = x*x. Compute f(3).
f(3) = 3*3
f(3) = 9
Answer: 9

Question: h(x) = x*x - 2x. Compute h(5).
h(5) = 5*5 - 2*5
h(5) = 25 - 10
h(5) = 15
Answer: 15

Question: y(x) = x**3 - 2x. Compute y(3).
y(3) = 3**3 - 2*3
y(3) = 3*3*3 - 6
y(3) = 27 - 6
y(3) = 21
Answer: 21

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I could then ask it any of the following, and it would correctly show its work.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-md&#34;&gt;Question: f(x) = tan(x) + 1. Compute f(0).
Question: f(x) = sqrt(x) + 1. Compute f(16).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When I tried to give it&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-md&#34;&gt;Question: f(x) = x/2 + 2. Compute f(f(16)).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;it treated it as just &lt;code&gt;Compute f(16)&lt;/code&gt; rather than &lt;code&gt;f(f(16))&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Interestingly this works:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-md&#34;&gt;Question: f(x) = x*x. Compute f(3).
f(3) = 3*3
f(3) = 9
Answer: 9

Question: h(x) = x*x - 2x. Compute h(5).
h(5) = 5*5 - 2*5
h(5) = 25 - 10
h(5) = 15
Answer: 15

Question: f(x) = x/2 + 2. Compute f(f(16)).
f(f(16)) = f(16/2 + 2)
f(f(16)) = f(8 + 2)
f(f(16)) = f(10)
f(f(16)) = 10/2 + 2
f(f(16)) = 5 + 2
f(f(16)) = 7
Answer: 7

Question: y(x) = x**3 - 2x. Compute y(3).
y(3) = 3**3 - 2*3
y(3) = 3*3*3 - 6
y(3) = 27 - 6
y(3) = 21
Answer: 21

Question: f(x) = x*3 - 1. Compute f(f(5)).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Whereas this does not:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-md&#34;&gt;Question: f(x) = x*x. Compute f(3).
f(3) = 3*3
f(3) = 9
Answer: 9

Question: h(x) = x*x - 2x. Compute h(5).
h(5) = 5*5 - 2*5
h(5) = 25 - 10
h(5) = 15
Answer: 15

Question: f(x) = x*3 - 1. Compute f(f(5)).
f(f(5)) = f(5*3 - 1)
f(f(5)) = f(15 - 1)
f(f(5)) = f(14)
f(f(5)) = 14*3 - 1
f(f(5)) = 42 - 1
f(f(5)) = 41
Answer: 41

Question: y(x) = x**3 - 2x. Compute y(3).
y(3) = 3**3 - 2*3
y(3) = 3*3*3 - 6
y(3) = 27 - 6
y(3) = 21
Answer: 21

Question: f(x) = x/2 + 2. Compute f(f(16)).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After getting it to evaluate these simple expressions correctly, I also tried having it take derivatives. With an example as priming, and again having it show its work, this worked well. I haven&amp;rsquo;t performed a rigorous evaluation of its mathematical capabilities. For now, I&amp;rsquo;ve just begun to develop an intuition for how it works.&lt;/p&gt;
&lt;h2 id=&#34;part-3-playing-around&#34;&gt;Part 3: Playing Around&lt;/h2&gt;
&lt;p&gt;After doing math together, I tried many more things with GPT-3. I shared feelings with it, and it expanded on them (correctly too!). I used it to generate lists for brainstorming all manner of thing. The language model wrote love letters from inanimate objects. I tried to teach it to play Codenames, but with only very limited success. And I had it autocomplete previous snippets of mine, and had some fun cowriting with it. While I won&amp;rsquo;t be sharing all of this with you, I do have one thing to share.&lt;/p&gt;
&lt;p&gt;This is a love letter written by a frying pan:&lt;/p&gt;
&lt;p&gt;I may not seem like much to you right now. I&amp;rsquo;m coated in grease and I&amp;rsquo;m starting to rust, but really, I have big plans. I&amp;rsquo;m going to Italian restaurants. I&amp;rsquo;ll hang out with the finest (and healthiest) ingredients you can imagine. It was good knowing you, but you were never mine to keep. I&amp;rsquo;m going to cook the kind of meal you&amp;rsquo;ll dream about for the rest of your life. Good luck, sweetheart. You&amp;rsquo;ll need it.&lt;/p&gt;
&lt;h2 id=&#34;overall-principles&#34;&gt;Overall Principles&lt;/h2&gt;
&lt;p&gt;Getting an intuition for how GPT-3 behaves has been interesting, and I&amp;rsquo;ll try now to distill that intuition down into a few principles.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;GPT-3 is continuing your writing, not having a dialog with you.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I&amp;rsquo;ve seen on Twitter lots of people asking GPT-3 questions, and sharing its response. Know that GPT-3 continues whatever prompt you give it as if it had written the prompt itself, not as if it is responding to the prompt. This is why you often see prompts like &amp;ldquo;The following is a conversation between X and Y:&amp;rdquo;.&lt;/p&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;GPT-3 effectively puts your writing in a made up context.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you give GPT-3 a small prompt, such a single sentence, then there are many contexts in which that prompt could be interpreted. GPT-3 is trained to marginalize over the contexts in which the text could appear. Once you start decoding GPT-3&amp;rsquo;s response though, one implicit context has been selected. It might not be the context that you intended when writing your prompt.&lt;/p&gt;
&lt;p&gt;This can happen even if you try to set the context yourself explicitly. For example you might be trying to generate a conversation or a list, and GPT-3 might decide that this conversation or list is taking place inside of a novel.&lt;/p&gt;
&lt;p&gt;You can mitigate this context switch by using a longer prompt, or by doing more of the writing yourself.&lt;/p&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;GPT-3 likes lists and repeated structures.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is the main principle behind using GPT-3 for few shot learning. Prompt GPT-3 with a few examples of performing a task, and it will usually make an effort to perform that task yet again.&lt;/p&gt;
&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;GPT-3 cannot perform linguistic tricks like unscrambling words&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It doesn&amp;rsquo;t seem capable of generating new puns (I haven&amp;rsquo;t tried this yet).
And it doesn&amp;rsquo;t seem capable of unscrambling words (I did try this, and I couldn&amp;rsquo;t even get it to unscramble 4-letter words).&lt;/p&gt;
&lt;ol start=&#34;5&#34;&gt;
&lt;li&gt;GPT-3 benefits from &amp;ldquo;showing its work&amp;rdquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In my math experiments, having GPT-3 show its work was critical to getting it solving the math questions correctly. It seems that doing a single step of expression evaluation at a time is an easier task than doing it all at once. Providing examples with the steps gave GPT-3 a clearer explanation of the task than just providing input/output examples. GPT-3 also gets additional computational steps in which to solve the problem when it takes the time to show its work.&lt;/p&gt;
&lt;ol start=&#34;6&#34;&gt;
&lt;li&gt;GPT-3 has a great breadth of knowledge and writing styles available to it&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It can express love, write flowery prose, give advice, write technical documentation, latex, program, math, take the perspective of a toaster, and more. It&amp;rsquo;s a great tool for brainstorming both explicitly (by having it generate ideas) and through exploration (by using it to help you generate ideas yourself).&lt;/p&gt;
&lt;p&gt;Though it has all the facts from the internet at its fingertips (of all the ways to anthropomorphize GPT-3, why choose fingertips?), it is just as capable of generating falsehoods as truths. Do not mistake the text it generates as true or logically correct, even if in many circumstances it does generate correct information. When it transitions from generating truth to generating nonsense it does not give a warning that it has done so (and any truth it does generate is in a sense at least partially accidental).&lt;/p&gt;
&lt;ol start=&#34;7&#34;&gt;
&lt;li&gt;Sometimes GPT-3 makes no sense&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are things that don&amp;rsquo;t make sense that the language model assigns reasonable probabilities to. And there are things that don&amp;rsquo;t make sense, are low probability, but come up anyway either due to chance or because the model doesn&amp;rsquo;t have anything better to say. It doesn&amp;rsquo;t stop generating text just because its out of its depth. Instead, it just plods on forward, saying something as reasonable as it&amp;rsquo;s capable of, regardless of the situation it finds itself in.&lt;/p&gt;
&lt;ol start=&#34;8&#34;&gt;
&lt;li&gt;GPT-3 mimics your style&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you prompt GPT-3 with typos it will continue with typos. If you prompt GPT-3 with florid prose, it will write florid prose. If you prompt GPT-3 with anaphora laden rhetoric, or any other style, it will continue in that style.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ll let GPT-3 wrap things up itself:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;And that brings us to the end, some thoughts on whether using GPT-3 was more or less crazy than getting a Ph.D.. I think that using GPT-3 to generate ideas was a higher form of Enlightenment than any Ph.D. I&amp;rsquo;d do that again in a heartbeat, no shortage of ideas rolling around in GPT-3&amp;rsquo;s natural language processing head.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Uh huh. Whatever, GPT-3. Whatever.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Deep Variational Information Bottleneck</title>
      <link>https://davidbieber.com/snippets/2020-07-21-deep-variational-informational-bottleneck/</link>
      <pubDate>Tue, 21 Jul 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-07-21-deep-variational-informational-bottleneck/</guid>
      
      <description>&lt;p&gt;You can read the 2017 paper &amp;ldquo;Deep Variational Information Bottleneck&amp;rdquo; 
&lt;a href=&#34;https://arxiv.org/pdf/1612.00410.pdf&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;on Arxiv here&lt;/a&gt;, and its reviews are visible 
&lt;a href=&#34;https://openreview.net/forum?id=HyxQzBceg&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;on OpenReview here&lt;/a&gt;. The authors are my coworkers: Alex Alemi, Ian Fischer, Joshua Dillon, and Kevin Murphy.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve taken notes on the paper, and will use this snippet to present them.&lt;/p&gt;
&lt;h2 id=&#34;notation&#34;&gt;Notation&lt;/h2&gt;
&lt;p&gt;We consider the problem of supervised learning for classification with the following notation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$X$: An example input.&lt;/li&gt;
&lt;li&gt;$Z$: The output of an intermediate layer of a neural network.
&lt;ul&gt;
&lt;li&gt;We view this as a stochastic encoding of $X$.&lt;/li&gt;
&lt;li&gt;It is the output of a parametric encoder $p(\textbf{z} | \textbf{x}; \theta)$&lt;/li&gt;
&lt;li&gt;$\theta$ are the parameters of the neural network used to encode $X$ that we wish to learn.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;$Y$: The example&amp;rsquo;s target class.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;goal&#34;&gt;Goal&lt;/h2&gt;
&lt;p&gt;The approach of the paper aims first and foremost to learn an encoding $Z$ of $X$ that is maximally informative about $Y$.
This is measured via mutual information between $Z$ and $Y$: $I(Z, Y; \theta)$.&lt;/p&gt;
&lt;p&gt;$$I(Z, Y; \theta) = \int dx~dy~p(z, y|\theta) \log \frac{p(z, y)}{p(z)p(y)}$$&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not enough to maximize $I(Z, Y; \theta)$ though; this can be done by simply letting $Z = X$, which isn&amp;rsquo;t useful.&lt;/p&gt;
&lt;p&gt;So, we also want to limit $I(Z, X)$. We do this by enforcing an information constraint: $I(X, Z) &amp;lt; I_c$.&lt;/p&gt;
&lt;p&gt;Our goal is to maximize $I(Z, Y; \theta)$ subject to $I(X, Z) &amp;lt; I_c$.&lt;/p&gt;
&lt;p&gt;Rewriting this using Lagrange multiplier $\beta$ brings us to the information bottleneck (IB) objective, which we write as follows:&lt;/p&gt;
&lt;p&gt;$$R_{IB}(\theta) = I(Z,Y) - \beta I(Z, X).$$&lt;/p&gt;
&lt;p&gt;The goal of the paper is to maximize $R_{IB}$.&lt;/p&gt;
&lt;h2 id=&#34;intuition-behind-goal&#34;&gt;Intuition Behind Goal&lt;/h2&gt;
&lt;p&gt;Why maximize $I(Z, Y)$? This is what allows the model to make correct predictions.&lt;/p&gt;
&lt;p&gt;Why not just maximize $I(Z, Y)$? Letting $Z = X$ fully maximizes $I(Z, Y)$, but isn&amp;rsquo;t helpful because the representation of $Z$ is what you started with, so its hard to make good classifications.&lt;/p&gt;
&lt;p&gt;Why minimize $\beta I(Z, X)$? We want a representation $Z$ that is maximally compressive of the input $X$.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s the intuition given in the paper for why we seek to minimize $\beta I(Z, X)$, but it isn&amp;rsquo;t clear the degree to which compression is useful. Yes, a compressive representation of $X$ can lead to better generalization, but it&amp;rsquo;s a trade off. Greater compression may mean lower $I(Z, Y)$ and hence lower potential accuracy. Balancing this trade off (choosing an appropriate $\beta$) will be important.&lt;/p&gt;
&lt;h2 id=&#34;why-is-it-difficult&#34;&gt;Why is it difficult?&lt;/h2&gt;
&lt;p&gt;Mutual information is in general intractable. So we can&amp;rsquo;t directly optimize the object $R_{IB}(\theta)$ as stated in the goal. Instead, the paper takes the following approach to get around mutual information&amp;rsquo;s intractability.&lt;/p&gt;
&lt;h2 id=&#34;the-approach&#34;&gt;The Approach&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Use variational inference to construct a lower bound on the IB objective.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the &amp;ldquo;reparameterization trick&amp;rdquo; and Monte Carlo sampling to get unbiased estimate of gradient.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Parameterize our distributions with neural networks, and optimize with SGD.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We&amp;rsquo;ll go into more detail in just a minute.&lt;/p&gt;
&lt;h2 id=&#34;benefits&#34;&gt;Benefits&lt;/h2&gt;
&lt;p&gt;This approach provides some robustness to overfitting because model ignores as much of $X$ as possible.&lt;/p&gt;
&lt;p&gt;It also provides some robustness to adversarial examples because the model maps $X$ to a distribution over $Z$s rather than a single $Z$, so its harder for a single unusual value to influence a final class prediction.&lt;/p&gt;
&lt;h2 id=&#34;execution&#34;&gt;Execution&lt;/h2&gt;
&lt;h3 id=&#34;part-1-variational-inference&#34;&gt;Part 1: Variational Inference&lt;/h3&gt;
&lt;p&gt;You can follow the math in the paper (Section 3), but the first main result is to define&lt;/p&gt;
&lt;p&gt;$$L = \int dx~dy~dz~ p(x) p(y|x) p(z|x) \log q(y|z) - \beta \int dx~dz~ p(x) p(z|x) \log \frac{p(z|x)}{r(z)}$$&lt;/p&gt;
&lt;p&gt;and show that
$$R_{IB}(\theta) = I(Z,Y) - \beta I(Z, X) \ge L.$$&lt;/p&gt;
&lt;p&gt;To achieve this, we&amp;rsquo;ve introduced $q(y|z)$ as an approximation of $p(y|z)$, and $r(z)$ as an approximation of $p(z)$.&lt;/p&gt;
&lt;p&gt;$L$ serves as a lower bound for the objective we care about. $p$, $q$, and $r$ are all parameterized by $\theta$.&lt;/p&gt;
&lt;p&gt;We can approximate $L$ as&lt;/p&gt;
&lt;p&gt;$$L \approx \frac{1}{N}\sum_{n=1}^N \left[\int dz~ p(z|x_n) \log q(y_n|z) - \beta~ p(z|x_n) \log \frac{p(z|x_n)}{r(z)} \right].$$&lt;/p&gt;
&lt;h3 id=&#34;part-2-reparameterization-trick&#34;&gt;Part 2: Reparameterization trick&lt;/h3&gt;
&lt;p&gt;Suppose $p(z|x)$ is $N(z|f_e^\mu(x), f_e^\Sigma(x))$, with $f_e$ a neural network that outputs the mean and covariance matrix for the Gaussian.&lt;/p&gt;
&lt;p&gt;Then the &amp;ldquo;reparameterization trick&amp;rdquo; is to write $p(z|x)dz = p(\epsilon)d\epsilon$, where $z = f(x, \epsilon)$ is a deterministic function and $\epsilon$ is a Gaussian random variable. Using this, we can rewrite $L$ as follows.&lt;/p&gt;
&lt;p&gt;$$J_{IB} = \frac{1}{N} \sum\limits_{n=1}^N E_{\epsilon \sim p(\epsilon)} \left[-\log q(y_n|f(x_n,\epsilon))\right] + \beta KL[p(Z|x_n), r(Z)]$$&lt;/p&gt;
&lt;p&gt;As long as $q$ is differentiable and $KL[p(Z|x_n), r(Z)]$ is tractable, this is an objective we can optimize with e.g. gradient descent.&lt;/p&gt;
&lt;h2 id=&#34;implementation&#34;&gt;Implementation&lt;/h2&gt;
&lt;p&gt;A concise demo implementation is available on GitHub at &lt;a href=&#34;https://github.com/alexalemi/vib_demo/blob/master/MNISTVIB.ipynb&#34;&gt;https://github.com/alexalemi/vib_demo/blob/master/MNISTVIB.ipynb&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve describe here the correspondence between the notation used in the source code and the notation used in the paper.
Terms from the paper are in $\LaTeX$, and terms from the source code are in &lt;code&gt;code blocks&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;class_loss&lt;/code&gt;: $-\log q(y_n | f(x_n, \epsilon))$ (comes from the $I(Z, Y)$ term)
&lt;ul&gt;
&lt;li&gt;Recall $z = f(x, \epsilon)$; this is &lt;code&gt;encoding.sample()&lt;/code&gt; in the code base.&lt;/li&gt;
&lt;li&gt;$q$ is &lt;code&gt;decoder&lt;/code&gt; with softmax applied, and $q(y | f(x_n, \epsilon))$ is softmax(&lt;code&gt;logits&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;class_loss = tf.losses.softmax_cross_entropy( logits=logits, onehot_labels=one_hot_labels) / math.log(2)&lt;/code&gt; is $-\log q(y_n | f(x_n, \epsilon))$
&lt;ul&gt;
&lt;li&gt;$f$ is &lt;code&gt;encoder&lt;/code&gt;, and $f(x, \cdot)$ is &lt;code&gt;encoding&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;$p(Z|x_n)$ is also &lt;code&gt;encoding&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;$f$ is the deterministic encoder used by the reparameterization trick, whereas $p$ is the stochastic encoder&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;$KL[p(Z|x_n), r(Z)]$ is &lt;code&gt;info_loss&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prior&lt;/code&gt; is $r(z)$ (which approximates $p(z)$).&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Downloading the Online Encylopedia of Integer Sequences</title>
      <link>https://davidbieber.com/snippets/2020-06-28-oeis-download/</link>
      <pubDate>Sun, 28 Jun 2020 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-06-28-oeis-download/</guid>
      
      <description>&lt;p&gt;If you&amp;rsquo;re looking for a way to download the entire 
&lt;a href=&#34;https://oeis.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Online Encylopedia of Integer Sequences&lt;/a&gt;, you may come across advice for scraping the site, one sequence at a time. Instead of collecting the sequences one at a time, it might be sufficient to download one of their already collected archives. 
&lt;a href=&#34;https://oeis.org/stripped.gz&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;This file&lt;/a&gt; contains the integer sequences and their A-numbers, and 
&lt;a href=&#34;https://oeis.org/names.gz&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;this file&lt;/a&gt; contains the names of the sequences. No need to stress the OEIS servers when these ready-made archives are ripe for downloading!&lt;/p&gt;
&lt;p&gt;I found these files from 
&lt;a href=&#34;https://oeis.org/wiki/JSON_Format,_Compressed_Files&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;this page&lt;/a&gt; of the OEIS wiki. The reason I&amp;rsquo;m linking to it here is that finding that page was difficult, and I hope to save you the trouble of finding it for yourself.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Facebook Mobile Website: News Feed in Chronological Order</title>
      <link>https://davidbieber.com/snippets/2020-06-28-facebook-chronological-order/</link>
      <pubDate>Sun, 28 Jun 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-06-28-facebook-chronological-order/</guid>
      
      <description>&lt;p&gt;On your phone, you can navigate to 
&lt;a href=&#34;https://www.facebook.com/home.php?sk=h_chr&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://www.facebook.com/home.php?sk=h_chr&lt;/a&gt; to view your News Feed on the Facebook website in chronological order.&lt;/p&gt;
&lt;p&gt;There are also excellent apps for hiding your Facebook News Feed if you find it draining on your attention, but unfortunately they don&amp;rsquo;t work on mobile:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href=&#34;https://www.hidefeed.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Hide Feed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://chrome.google.com/webstore/detail/news-feed-eradicator-for/fjcldmjmjhkklehbacihaiopjklihlgg?hl=en&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Facebook News Feed Eradicator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since these don&amp;rsquo;t work on the Facebook mobile website, I&amp;rsquo;ve turned to this new strategy to combat the attention draining nature of News Feed: only viewing my feed in chronological order.&lt;/p&gt;
&lt;p&gt;By switching to chronological order, the &amp;ldquo;infinite scroll&amp;rdquo; of the News Feed is interrupted because either you eventually get to posts you&amp;rsquo;ve seen before, or you notice the timestamp of the posts you&amp;rsquo;re looking at slowly rising. You also get a more complete picture of what content is available, which helps fight the constant &amp;ldquo;just one more post&amp;rdquo; feeling that drives infinite scrolling.&lt;/p&gt;
&lt;p&gt;So, how do you switch your news feed to chronological order?&lt;/p&gt;
&lt;p&gt;On the main Facebook website, you can click the three dots next to &amp;ldquo;News Feed&amp;rdquo; and choose &amp;ldquo;Most Recent&amp;rdquo;. However, you have to choose this option every time you visit Facebook, which can be frustrating. So instead, navigate directly to 
&lt;a href=&#34;https://www.facebook.com/home.php?sk=h_chr&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://www.facebook.com/home.php?sk=h_chr&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On the Facebook mobile website, there isn&amp;rsquo;t an option to view posts in chronological order. Instead, you can achieve this by accessing the desktop website on your phone. Go to 
&lt;a href=&#34;https://www.facebook.com/home.php?sk=h_chr&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://www.facebook.com/home.php?sk=h_chr&lt;/a&gt; to get the Desktop version of Facebook on your phone, with chronological order already enabled. Bookmark the page and use it as your primary way of accessing Facebook on your phone to get chronological order as your News Feed default from now on.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Accessing Your iMessages with SQL</title>
      <link>https://davidbieber.com/snippets/2020-05-20-imessage-sql-db/</link>
      <pubDate>Wed, 20 May 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-05-20-imessage-sql-db/</guid>
      
      <description>&lt;p&gt;If you use a Mac and use iMessage, you can access your iMessages programmatically. They are stored by iMessage as a sqlite database, which you can easily access.&lt;/p&gt;
&lt;h2 id=&#34;accessing-the-database&#34;&gt;Accessing the Database&lt;/h2&gt;
&lt;p&gt;The database is typically stored at &lt;code&gt;~/Library/Messages/chat.db&lt;/code&gt;, though that location is configurable.&lt;/p&gt;
&lt;p&gt;If you try to access the database, however, you will likely encounter this unhelpful error message: &lt;code&gt;~/Library/Messages/chat.db: Operation not permitted&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Thankfully, OSXDaily has put together a 
&lt;a href=&#34;https://osxdaily.com/2018/10/09/fix-operation-not-permitted-terminal-error-macos/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;helpful step by step guide to resolving this error&lt;/a&gt;, which I&amp;rsquo;ll summarize here:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Navigate to your &lt;code&gt;System Preferences &amp;gt; Security &amp;amp; Privacy &amp;gt; Privacy &amp;gt; Full Disk Access&lt;/code&gt; settings.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the Lock and &lt;code&gt;+&lt;/code&gt; symbol to give full disk access to the Terminal App (located in &lt;code&gt;Applications &amp;gt; Utilities &amp;gt; Terminal&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You may need to relaunch Terminal for the change to take effect; I did not.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once you&amp;rsquo;ve done this, you can start poking around at your iMessages programmatically.&lt;/p&gt;
&lt;h2 id=&#34;taking-a-look-around&#34;&gt;Taking a Look Around&lt;/h2&gt;
&lt;p&gt;I begin with making a backup:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cp ~/Library/Messages/chat.db ~/chat.db&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now I open the database with sqlite3.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sqlite3 ~/chat.db&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I run &lt;code&gt;.tables&lt;/code&gt; to see what tables there are:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;_SqliteDatabaseProperties&lt;/td&gt;
&lt;td&gt;kvtable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;attachment&lt;/td&gt;
&lt;td&gt;message&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;chat&lt;/td&gt;
&lt;td&gt;message_attachment_join&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;chat_handle_join&lt;/td&gt;
&lt;td&gt;message_processing_task&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;chat_message_join&lt;/td&gt;
&lt;td&gt;sync_deleted_attachments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;deleted_messages&lt;/td&gt;
&lt;td&gt;sync_deleted_chats&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;handle&lt;/td&gt;
&lt;td&gt;sync_deleted_messages&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;There are some interesting tables in there: &lt;code&gt;message&lt;/code&gt; seems most important. It looks like we&amp;rsquo;ll also be able to look up attachments using tables &lt;code&gt;attachment&lt;/code&gt; and &lt;code&gt;message_attachment_join&lt;/code&gt;. Strangely, there&amp;rsquo;s a table present for deleted messages, which suggests a sort of &amp;ldquo;trash can&amp;rdquo; where messages are not permanently deleted immediately upon deletion.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.schema message&lt;/code&gt; is the command for viewing the schema of the message table.
We can also jump right in with &lt;code&gt;SELECT * FROM message;&lt;/code&gt; to see what sort of data is contained within. Sure enough, human readable messages are present.&lt;/p&gt;
&lt;p&gt;This will all be interesting to investigate further at a later date.
One perk of understanding this mechanism for me is that I&amp;rsquo;ll be able to write events that are triggered in response to iMessages. This enables me to write custom notification criteria. For example, I can have messages that start &amp;ldquo;URGENT&amp;rdquo; notify me immediately, but I can have all other messages programatically withheld from notifying me until 9pm.&lt;/p&gt;
&lt;p&gt;This lets me receive the messages at the time and location that I want, rather than at the time Apple chooses for me. Thanks Bieber Bot.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Taking Notes While Browsing the Web: An Idea for a Roam Research Plugin</title>
      <link>https://davidbieber.com/snippets/2020-05-15-roaming-the-web/</link>
      <pubDate>Fri, 15 May 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-05-15-roaming-the-web/</guid>
      
      <description>&lt;p&gt;As I&amp;rsquo;m browsing the web, I&amp;rsquo;d like to be able to take notes in 
&lt;a href=&#34;https://roamresearch.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Roam Research&lt;/a&gt;. In this post, I share an idea I have for a plugin or browser extension that I think would improve the experience of taking notes in Roam while browsing the web.&lt;/p&gt;
&lt;p&gt;The plugin would do two main things automatically:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;It would automatically insert some browsing history information into your Roam database while you browse the internet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;As you navigate the web, it would automatically bring you to the Roam page that corresponds to the web page you&amp;rsquo;re reading.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;mind-the-details&#34;&gt;Mind the Details&lt;/h2&gt;
&lt;p&gt;Of course, the implementation details matter! You don&amp;rsquo;t want to be whisked away from the notes you&amp;rsquo;re taking just because you&amp;rsquo;ve clicked a link in a different window.&lt;/p&gt;
&lt;p&gt;So, here I&amp;rsquo;ll explain a few of the details I think would make this a good note taking experience.&lt;/p&gt;
&lt;p&gt;As I&amp;rsquo;m browsing the internet, all the websites I visit will get added to a page &amp;ldquo;{Date} Browsing History&amp;rdquo;. A new Roam page will be created for each new website visited. And there will be a Roam window that always stays open to the Roam page for the current website I have open in my browser.&lt;/p&gt;
&lt;p&gt;What qualifies as a website?&lt;/p&gt;
&lt;p&gt;By default there would be one Roam page per &lt;em&gt;domain&lt;/em&gt; visited. However, there are several exceptions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For &lt;strong&gt;Wikipedia&lt;/strong&gt; it would be one Roam page per Wikipedia entry&lt;/li&gt;
&lt;li&gt;For websites reached from &lt;strong&gt;HackerNews&lt;/strong&gt;, &lt;strong&gt;Twitter&lt;/strong&gt;, and &lt;strong&gt;Reddit&lt;/strong&gt;, it would be one Roam page per link followed from the aggregator (but links followed within the reached website would not count as new websites)&lt;/li&gt;
&lt;li&gt;For &lt;strong&gt;GitHub&lt;/strong&gt; it would be one Roam page per user, organization, or repo visited&lt;/li&gt;
&lt;li&gt;For &lt;strong&gt;Arxiv&lt;/strong&gt; it would be one Roam page per paper&lt;/li&gt;
&lt;li&gt;For &lt;strong&gt;Roam&lt;/strong&gt; it would be one Roam page per Roam database&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It will be great to have a window that always stays open to the Roam page for the current website I have open in my browser. This way if I visit a website I&amp;rsquo;ve been to before, I will see my notes from that website. And the websites I visit will be linked to the day I visit them on, and also to any other pages my notes reference.&lt;/p&gt;
&lt;p&gt;Additionally, the tool should add a little bit of metadata to the pages it&amp;rsquo;s generating. On each of the autogenerated Roam pages, it would be great to see &lt;em&gt;when&lt;/em&gt; I visited the website, and what was the referring page. For websites visited multiple times, seeing the earliest and most recent visit times, and the number of times I visited that website would be useful too. Total time spent on the website would be a nice bonus.&lt;/p&gt;
&lt;h2 id=&#34;making-this-a-reality&#34;&gt;Making this a Reality&lt;/h2&gt;
&lt;p&gt;In the previous section I shared the details that I think would make this work well from a user experience perspective. How about from the technical side?&lt;/p&gt;
&lt;p&gt;I think it would make sense to implement this as a browser extension (though a 
&lt;a href=&#34;http://www.tampermonkey.net/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;em&gt;user script&lt;/em&gt;&lt;/a&gt; could work too).

&lt;a href=&#34;http://dkthehuman.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;DK the Human&lt;/a&gt;, author of the 
&lt;a href=&#34;https://chrome.google.com/webstore/detail/intention/dladanhaondcgpahgiflodhckhoeohoe&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Intention&lt;/a&gt; browser extension
has made his 
&lt;a href=&#34;https://github.com/dkthehuman/extension-starter-kit&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;browser extension starter kit&lt;/a&gt; freely available.
To notice when what web page you&amp;rsquo;re browsing and determine whether it constitutes a new page, the extension would need to request permission to view your activity on all websites.
For making additions to a Roam database automatically, I expect the extension would have to navigate to the appropriate Roam page in the background, and would then mimic the user actions to make the desired changes.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re interested in turning this idea into a reality or want to discuss it further, don&amp;rsquo;t hesitate to 
&lt;a href=&#34;mailto:david810&amp;#43;blog@gmail.com&#34;&gt;reach out&lt;/a&gt;! I&amp;rsquo;d be excited to try a workflow like this, but don&amp;rsquo;t anticipate building it myself in the near future.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Posting to Hacker News Programmatically</title>
      <link>https://davidbieber.com/snippets/2020-05-02-hackernews-submit/</link>
      <pubDate>Sat, 02 May 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-05-02-hackernews-submit/</guid>
      
      <description>&lt;p&gt;If you run this snippet of Python code, it will submit this 
&lt;a href=&#34;https://davidbieber.com/snippets/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&amp;ldquo;Snippet&amp;rdquo;&lt;/a&gt; (the one you&amp;rsquo;re currently reading) to Hacker News.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;from html.parser import HTMLParser
import getpass
import requests
import time

USERNAME = (
    &#39;&#39;  # Put your Hacker News username here.
    or getpass.getuser()  # (But if you don&#39;t, we&#39;ll try a sensible default.)
)
PASSWORD = (
    &#39;&#39;  # We&#39;ll prompt you for your password, or you can enter it here.
    or getpass.getpass()
)
# You can reconfigure the title and url to submit here.
TITLE_TO_SUBMIT = &#39;Posting to Hacker News Programmatically&#39;
URL_TO_SUBMIT = &#39;https://davidbieber.com/snippets/2020-05-02-hackernews-submit/&#39;

# Login
session = requests.Session()
session.post(
    &#39;https://news.ycombinator.com/login&#39;,
    data={
        &#39;acct&#39;: USERNAME,
        &#39;pw&#39;: PASSWORD,
    },
)

# Get the CSRF token (&amp;quot;FNID&amp;quot;)
time.sleep(1)
class FNIDExtractor(HTMLParser):
  fnid = None
  def handle_starttag(self, tag, attrs):
    if tag.lower() == &#39;input&#39; and (&#39;name&#39;, &#39;fnid&#39;) in attrs:
      self.fnid = dict(attrs)[&#39;value&#39;]
f = FNIDExtractor()
submit_response = session.get(&#39;https://news.ycombinator.com/submit&#39;)
f.feed(submit_response.text)

# Submit
time.sleep(2)
session.post(
    &#39;https://news.ycombinator.com/r&#39;,
    data={
        &#39;title&#39;: TITLE_TO_SUBMIT,
        &#39;url&#39;: URL_TO_SUBMIT,
        &#39;fnid&#39;: f.fnid,
    },
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can change the title and URL before running this to make a new submission, or run it as is to submit this snippet.&lt;/p&gt;
&lt;p&gt;If you try to submit a URL that&amp;rsquo;s already been submitted recently &amp;ndash; such as this snippet &amp;ndash; it won&amp;rsquo;t submit a second time, so no harm done in running this.&lt;/p&gt;
&lt;p&gt;To learn more about sessions and see why this works, you can read about them in the 
&lt;a href=&#34;https://requests.readthedocs.io/en/master/user/advanced/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;em&gt;requests&lt;/em&gt; documentation&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Detecting My Sleeping Hours from Data</title>
      <link>https://davidbieber.com/snippets/2020-04-30-detecting-sleeping-hours/</link>
      <pubDate>Thu, 30 Apr 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-04-30-detecting-sleeping-hours/</guid>
      
        <message>In this snippet I share a SQL query that estimates how much I sleep each night using only data collected from Facebook Messenger. It&#39;s not great.</message>
      
      <description>&lt;p&gt;Between my 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-04-20-browser-history-date-queries/&#34;&gt;Chrome browsing history&lt;/a&gt; and my 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-04-12-fb-messenger-sql/&#34;&gt;Facebook Messenger message logs&lt;/a&gt;, I should be able to get a good estimate of when I&amp;rsquo;m awake and asleep.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a quick attempt using only Messenger data.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;SELECT * FROM
  (SELECT to_timestamp(timestamp / 1000), (timestamp - lag(timestamp) over (ORDER BY timestamp DESC)) / 1000 / 60 / 60 AS diff_hours
   FROM messenger WHERE messenger.author = &#39;1409114395&#39; ORDER BY timestamp DESC LIMIT 100000) AS foo
WHERE diff_hours &amp;lt; -6;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately, my late night and early morning Messenger usage doesn&amp;rsquo;t appear to be as consistent as I&amp;rsquo;d imagined, especially since COVID-19 induced shelter-in-place began.
I&amp;rsquo;ll have to introduce additional sources of data if I want to infer good sleep time estimates.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Daily Summaries of Browsing History</title>
      <link>https://davidbieber.com/snippets/2020-04-26-daily-browser-history-summaries/</link>
      <pubDate>Sun, 26 Apr 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-04-26-daily-browser-history-summaries/</guid>
      
      <description>&lt;p&gt;Over the 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-04-12-simplifying-sql-with-with/&#34;&gt;course&lt;/a&gt; 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-04-20-browser-history-date-queries/&#34;&gt;of&lt;/a&gt; 
&lt;a href=&#34;https://davidbieber.com/snippets/2019-12-30-analyzing-my-browser-history/&#34;&gt;multiple&lt;/a&gt; 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-03-19-browsing-history/&#34;&gt;previous&lt;/a&gt; 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-04-11-browser-history-queries/&#34;&gt;snippets&lt;/a&gt;, I put together several SQL queries for analyzing my browsing history.&lt;/p&gt;
&lt;p&gt;Today, I wanted to write a script to run several of these queries in sequence to assemble a nice summary of my daily browsing histories. Maybe I&amp;rsquo;ll dump the summary into my 
&lt;a href=&#34;https://roamresearch.com/#/app/commons-db/page/wYVaowjId&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;[[Roam Research]]&lt;/code&gt;&lt;/a&gt; database so I can cross-link ideas with websites I&amp;rsquo;ve visited.&lt;/p&gt;
&lt;p&gt;As a first pass, I tried to throw together a quick bash script to string the queries together. It looked a bit like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;date=$1
if [ -z $1 ];
then
  date=$(date &#39;+%Y-%m-%d&#39;);
fi

cp ~/Library/Application\ Support/Google/Chrome/Default/History ~/Default-History
cp ~/Library/Application\ Support/Google/Chrome/Profile\ 1/History ~/Profile-1-History

function query() {
  sqlite3 ~/Default-History $1;
  sqlite3 ~/Profile-1-History $1;
}

echo \# YouTube Videos Watched
echo

query &amp;lt;&amp;lt; SQL
select DISTINCT REPLACE(REPLACE(urls.title, &amp;quot; - YouTube&amp;quot;, &amp;quot;&amp;quot;), &amp;quot;(1) &amp;quot;, &amp;quot;&amp;quot;), urls.url, &amp;quot;$date%&amp;quot;
from urls
where urls.url like &amp;quot;%www.youtube.com/watch%&amp;quot;
and datetime(last_visit_time / 1000000 + (strftime(&#39;%s&#39;, &#39;1601-01-01&#39;)), &#39;unixepoch&#39;)
LIKE &amp;quot;$date%&amp;quot;
limit 50;
SQL

# Additional queries ran here...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You&amp;rsquo;ll notice a few things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I want to run each query on two different Chrome histories.&lt;/li&gt;
&lt;li&gt;I want the script to be parameterized by the date, defaulting to today if no date is specified.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you&amp;rsquo;re proficient in Bash, you may also notice something else; it doesn&amp;rsquo;t work. The query is only used properly when I run sqlite3 on the first Chrome History, but an empty query is passed to the second query.&lt;/p&gt;
&lt;p&gt;Rather than debug my Bash script, I switched over to Python. I used Python Fire to automatically expose all my functions as commands so within minutes I had a working CLI.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what the Python script looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import datetime
import os
import subprocess

import fire


def copy_histories():
  check_output = subprocess.check_output
  check_output([
      &#39;cp&#39;,
      os.path.expanduser(&#39;~/Library/Application Support/Google/Chrome/Default/History&#39;),
      os.path.expanduser(&#39;~/Default-History&#39;)])
  check_output([
      &#39;cp&#39;,
      os.path.expanduser(&#39;~/Library/Application Support/Google/Chrome/Profile 1/History&#39;),
      os.path.expanduser(&#39;~/Profile-1-History&#39;)])


def run_query(query):
  call = subprocess.call
  call([&#39;sqlite3&#39;,  os.path.expanduser(&#39;~/Default-History&#39;), query])
  call([&#39;sqlite3&#39;, os.path.expanduser(&#39;~/Profile-1-History&#39;), query])


def run(date=None):
  copy_histories()
  date = date or datetime.datetime.now().strftime(&#39;%Y-%m-%d&#39;)

  print(&#39;## YouTube Videos Watched&#39;)
  print()

  run_query(f&amp;quot;&amp;quot;&amp;quot;
  select DISTINCT REPLACE(REPLACE(urls.title, &amp;quot; - YouTube&amp;quot;, &amp;quot;&amp;quot;), &amp;quot;(1) &amp;quot;, &amp;quot;&amp;quot;)
  from urls
  where urls.url like &amp;quot;%www.youtube.com/watch%&amp;quot;
  and datetime(last_visit_time / 1000000 + (strftime(&#39;%s&#39;, &#39;1601-01-01&#39;)), &#39;unixepoch&#39;)
  LIKE &amp;quot;{date}%&amp;quot;
  limit 50;
  &amp;quot;&amp;quot;&amp;quot;)

  # Additional queries run here...

if __name__ == &#39;__main__&#39;:
  fire.Fire()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At the command line I run this with &lt;code&gt;python historyquery.py run&lt;/code&gt; or &lt;code&gt;python historyquery.py run --date=2020-04-26&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With Python Fire I was able to quickly switch to a syntax I was more comfortable with, but keep the benefits of working from the context of a shell. I can now much more quickly make improvements to the script since I can operate more efficiently working in Python.&lt;/p&gt;
&lt;p&gt;Now I have a script I can run that will produce a nice summary of my internet browsing activity for any date I specify. Running it over recent dates provides a nice walk down memory lane.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Roam Research&#39;s JSON Export Format</title>
      <link>https://davidbieber.com/snippets/2020-04-25-roam-json-export/</link>
      <pubDate>Sat, 25 Apr 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-04-25-roam-json-export/</guid>
      
      <description>&lt;p&gt;
&lt;a href=&#34;https://roamresearch.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Roam Research&lt;/a&gt; is a note taking tool that makes it really low-friction to take deeply interwoven notes.
One of its core features is that you can effortlessly add links between pages in your notes, just by surrounding a name with square brackets, e.g. 
&lt;a href=&#34;https://roamresearch.com/#/app/commons-db/page/wYVaowjId&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;[[Roam Research]]&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Roam allows its users to export their Roam database as a JSON file. In this snippet, I describe the JSON format used and some of its implications.&lt;/p&gt;
&lt;h2 id=&#34;exporting-data-from-roam&#34;&gt;Exporting Data from Roam&lt;/h2&gt;
&lt;p&gt;From the triple-dots menu, select Export All. Choose JSON as the export format. Then click the Export All button. Your complete Roam database will download as a JSON file.&lt;/p&gt;
&lt;h2 id=&#34;roams-json-format&#34;&gt;Roam&amp;rsquo;s JSON Format&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;ll refer to the Roam JSON object you just downloaded as &lt;code&gt;data&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;data&lt;/code&gt; is a list, with each entry in &lt;code&gt;data&lt;/code&gt; corresponding to a single Roam &lt;code&gt;page&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Each &lt;code&gt;page&lt;/code&gt; is an object with keys: &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;children&lt;/code&gt;, &lt;code&gt;create-time&lt;/code&gt;, &lt;code&gt;create-email&lt;/code&gt;, &lt;code&gt;edit-time&lt;/code&gt;, &lt;code&gt;edit-email&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;page-schema&#34;&gt;Page Schema&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;title&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;The page title.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;children&lt;/td&gt;
&lt;td&gt;List[Child]&lt;/td&gt;
&lt;td&gt;The list of children of the page.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;create-time&lt;/td&gt;
&lt;td&gt;Integer&lt;/td&gt;
&lt;td&gt;The time (ms since epoch) when the page was created.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;create-email&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;The email of the person to create the page.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;edit-time&lt;/td&gt;
&lt;td&gt;Integer&lt;/td&gt;
&lt;td&gt;The time (ms since epoch) of the last edit to the page.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;edit-email&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;The email of the last person to edit the page.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Note that only &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;edit-time&lt;/code&gt;, and &lt;code&gt;edit-email&lt;/code&gt; appear to be required fields.
&lt;code&gt;children&lt;/code&gt;, &lt;code&gt;create-time&lt;/code&gt;, and &lt;code&gt;create-email&lt;/code&gt; appear to be omitted when not available.&lt;/p&gt;
&lt;h3 id=&#34;child-schema&#34;&gt;Child Schema&lt;/h3&gt;
&lt;p&gt;Each of the children in a page may have the following keys. Only the &lt;code&gt;uid&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;edit-time&lt;/code&gt;, and &lt;code&gt;edit-email&lt;/code&gt; keys seem universal. The rest may be omitted when not available.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;uid&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;A short unique identifier for the child.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;The string content of the child.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;children&lt;/td&gt;
&lt;td&gt;List[Child]&lt;/td&gt;
&lt;td&gt;The list of children of this child.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;create-time&lt;/td&gt;
&lt;td&gt;Integer&lt;/td&gt;
&lt;td&gt;The time (ms since epoch) when the page was created.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;create-email&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;The email of the person to create the page.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;edit-time&lt;/td&gt;
&lt;td&gt;Integer&lt;/td&gt;
&lt;td&gt;The time (ms since epoch) of the last edit to the page.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;edit-email&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;The email of the last person to edit the page.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Some children may additionally have the following keys.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;heading&lt;/td&gt;
&lt;td&gt;Integer&lt;/td&gt;
&lt;td&gt;1, 2, or 3; indicates the note is an h1, h2, or h3 heading.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;emojis&lt;/td&gt;
&lt;td&gt;List[Emoji]&lt;/td&gt;
&lt;td&gt;A list of objects indicating who added what emojis and when.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;text-align&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;One of &amp;lsquo;left&amp;rsquo;, &amp;lsquo;right&amp;rsquo;, &amp;lsquo;center&amp;rsquo;, or &amp;lsquo;justify&amp;rsquo; indicating the text alignment.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Note that in Roam, children are referred to as &amp;ldquo;blocks&amp;rdquo;, and a child&amp;rsquo;s ID is the ID used to reference a block.&lt;/p&gt;
&lt;p&gt;Last but not least, I include the emoji reaction schema 😂.&lt;/p&gt;
&lt;h3 id=&#34;emoji-schema&#34;&gt;Emoji Schema&lt;/h3&gt;
&lt;p&gt;Each Emoji reaction to a child is an object conforming to the following schema.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;emoji&lt;/td&gt;
&lt;td&gt;object&lt;/td&gt;
&lt;td&gt;An object with a single key &lt;code&gt;native&lt;/code&gt; containing the emoji itself.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;users&lt;/td&gt;
&lt;td&gt;List[object]&lt;/td&gt;
&lt;td&gt;A list of objects indicating who added this emoji and when. The keys are &lt;code&gt;time&lt;/code&gt; (ms since epoch) and &lt;code&gt;email&lt;/code&gt; (the email of the user who added the reaction).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;missing-information&#34;&gt;Missing Information&lt;/h3&gt;
&lt;p&gt;Some information appears to get lost in the export. In particular, the following information appears to be dropped.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&amp;ldquo;View as Document&amp;rdquo; / &amp;ldquo;View as Numbered List&amp;rdquo;: This formatting information doesn&amp;rsquo;t seem to get exported.&lt;/li&gt;
&lt;li&gt;Versions. If you&amp;rsquo;re using the &amp;ldquo;versions&amp;rdquo; feature of Roam, the versions don&amp;rsquo;t seem to be exported either.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;implications-of-the-json-format&#34;&gt;Implications of the JSON Format&lt;/h2&gt;
&lt;p&gt;Since Roam allows export of its data in such a simple format, you can easily write scripts for processing this data. For example, merging two databases is trivial. I include some simple such scripts in the following section.&lt;/p&gt;
&lt;p&gt;The clear export also means that you will continue to be able to use your data long into the future, even if Roam shuts down or otherwise becomes unavailable to you. As long as you occasionally back up your data by exporting it, it is yours forever.&lt;/p&gt;
&lt;h2 id=&#34;useful-python-snippets-for-processing-roam-json&#34;&gt;Useful Python Snippets for Processing Roam JSON&lt;/h2&gt;
&lt;p&gt;Once you&amp;rsquo;ve downloaded your data as JSON from Roam, you can load and manipulate it as follows.&lt;/p&gt;
&lt;h3 id=&#34;load-json&#34;&gt;Load JSON&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import json
filepath = &#39;/path/to/roam-database.json&#39;
data = json.load(open(filepath))
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;collect-all-children&#34;&gt;Collect All Children&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;children = []
blocks = data.copy()
while blocks:
  block = blocks.pop()
  if &#39;children&#39; in block:
    blocks.extend(block[&#39;children&#39;])
    children.extend(block[&#39;children&#39;])
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;find-all-notes-mentioning-roam&#34;&gt;Find All Notes Mentioning &amp;ldquo;Roam&amp;rdquo;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;for child in children:
  if &#39;roam&#39; in child.get(&#39;string&#39;, &#39;&#39;).lower():
    print(child[&#39;string&#39;])
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;merge-two-databases&#34;&gt;Merge Two Databases&lt;/h3&gt;
&lt;p&gt;Since databases are just lists of objects, you can trivially merge them.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;merged = db1 + db2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&amp;rsquo;s possible this will result in multiple pages having the same name, but Roam deals with this just fine.&lt;/p&gt;
&lt;h2 id=&#34;thank-you-roam&#34;&gt;Thank You Roam&lt;/h2&gt;
&lt;p&gt;I want to conclude with a note of thanks to the Roam developers for allowing export in such a clear and readily understandable manner. Doing so inspires confidence that I will be able to continue using the notes I take in Roam far into the future, no matter what. This makes me so much more comfortable using Roam for my note taking. Props and thank you to the Roam developers for this feature.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Date and Time Browser History Queries</title>
      <link>https://davidbieber.com/snippets/2020-04-20-browser-history-date-queries/</link>
      <pubDate>Mon, 20 Apr 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-04-20-browser-history-date-queries/</guid>
      
      <description>&lt;p&gt;I wrote a 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-04-11-browser-history-queries/&#34;&gt;number of SQL queries&lt;/a&gt; for browsing my browsing history. In this snippet, I show how to amend them to filter the results by date. Google Chrome selects a slightly non-standard time storage format (microseconds since January 1, 1601 UTC), hence the need for this query stanza.&lt;/p&gt;
&lt;p&gt;To run these queries, first make a copy of your browser history and open it in sqlite3.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;cp ~/Library/Application\ Support/Google/Chrome/Default/History ~/my-history
sqlite3 ~/my-history
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;google-search-history-for-specific-date&#34;&gt;Google Search History for Specific Date&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s the query we had from before, for accessing our Google Search history.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT REPLACE(urls.title, &amp;quot; - Google Search&amp;quot;, &amp;quot;&amp;quot;)
from urls
where urls.url like &amp;quot;%www.google.com/search%&amp;quot; 
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To filtering by a specific date, we just add.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;AND
datetime(last_visit_time / 1000000 + (strftime(&#39;%s&#39;, &#39;1601-01-01&#39;)), &#39;unixepoch&#39;)
LIKE &#39;2019-12-25%&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What was I searching for on Christmas last year?&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT REPLACE(urls.title, &amp;quot; - Google Search&amp;quot;, &amp;quot;&amp;quot;)
from urls
where urls.url like &amp;quot;%www.google.com/search%&amp;quot; 
and datetime(last_visit_time / 1000000 + (strftime(&#39;%s&#39;, &#39;1601-01-01&#39;)), &#39;unixepoch&#39;)
LIKE &#39;2019-12-25%&#39;
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;youtube-videos-watched-today&#34;&gt;YouTube Videos Watched Today&lt;/h2&gt;
&lt;p&gt;To query for results from &lt;em&gt;today&lt;/em&gt;, we can do the following.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT REPLACE(urls.title, &amp;quot; - YouTube&amp;quot;, &amp;quot;&amp;quot;), urls.url, datetime(last_visit_time / 1000000 + (strftime(&#39;%s&#39;, &#39;1601-01-01&#39;)), &#39;unixepoch&#39;) as d
from urls
where urls.url like &amp;quot;%www.youtube.com/watch%&amp;quot;
and datetime(last_visit_time / 1000000 + (strftime(&#39;%s&#39;, &#39;1601-01-01&#39;)), &#39;unixepoch&#39;)
LIKE (date(&#39;now&#39;, &#39;localtime&#39;) || &#39;%&#39;)
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note the use of &lt;code&gt;localtime&lt;/code&gt; to account for the timezone. &lt;code&gt;||&lt;/code&gt; is used here for string concatenation.&lt;/p&gt;
&lt;h2 id=&#34;arxiv-papers-visited-last-month&#34;&gt;Arxiv Papers Visited Last Month&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT urls.title, REPLACE(REPLACE(urls.url, &amp;quot;.pdf&amp;quot;, &amp;quot;&amp;quot;), &amp;quot;/pdf/&amp;quot;, &amp;quot;/abs/&amp;quot;)
from urls
where (urls.url like &amp;quot;https://arxiv.org/abs%&amp;quot;
or urls.url like &amp;quot;https://arxiv.org/pdf%&amp;quot;)
and datetime(last_visit_time / 1000000 + (strftime(&#39;%s&#39;, &#39;1601-01-01&#39;)), &#39;unixepoch&#39;)
LIKE (substr(date(&#39;now&#39;, &#39;localtime&#39;, &#39;-1 month&#39;), 0, 9) || &#39;%&#39;)
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here you can see that &lt;code&gt;date&lt;/code&gt; gives flexibility in adjusting the date you are requesting. &lt;code&gt;substr&lt;/code&gt; is used to transform &lt;code&gt;2020-03-20&lt;/code&gt; to &lt;code&gt;2020-03-&lt;/code&gt;, to match any date in the month.&lt;/p&gt;
&lt;h2 id=&#34;hackernews-links-followed-in-the-last-week&#34;&gt;HackerNews Links Followed in the Last Week&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT urls.title, urls.url
from visits
join visits as previous_visits on visits.from_visit == previous_visits.id
join urls on urls.id == visits.url
join urls as previous_urls on previous_urls.id == previous_visits.url
where previous_urls.url like &amp;quot;https://news.ycombinator.com%&amp;quot;
and urls.url not like &amp;quot;https://news.ycombinator.com%&amp;quot;
and datetime(visits.visit_time / 1000000 + (strftime(&#39;%s&#39;, &#39;1601-01-01&#39;)), &#39;unixepoch&#39;)
&amp;gt; date(&#39;now&#39;, &#39;localtime&#39;, &#39;-7 day&#39;)
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For this query, we directly compare the result of &lt;code&gt;datetime&lt;/code&gt; and &lt;code&gt;date&lt;/code&gt;.

&lt;a href=&#34;https://www.sqlite.org/lang_datefunc.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;sqlite.org/lang_datefunc.html&lt;/a&gt; has more useful information about writing queries manipulating dates and times.&lt;/p&gt;
&lt;p&gt;For more query ideas, here&amp;rsquo;s the 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-04-11-browser-history-queries/&#34;&gt;link back to the browser history queries snippet&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Simplifying SQL Queries with &#34;WITH&#34;</title>
      <link>https://davidbieber.com/snippets/2020-04-12-simplifying-sql-with-with/</link>
      <pubDate>Sun, 12 Apr 2020 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-04-12-simplifying-sql-with-with/</guid>
      
      <description>&lt;p&gt;In the 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-04-11-browser-history-queries/&#34;&gt;&amp;ldquo;More Browser History Queries&amp;rdquo; snippet&lt;/a&gt; one of the SQL queries I wrote was particularly nasty.&lt;/p&gt;
&lt;p&gt;Since I didn&amp;rsquo;t know how to introduce intermediate variables, I had to replicate subqueries multiple times throughout the query. The result was a mess of a query. Using &lt;code&gt;WITH&lt;/code&gt; clauses, the query becomes considerably more readable and maintainable.&lt;/p&gt;
&lt;h2 id=&#34;cleaned-up-query&#34;&gt;Cleaned up Query&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s the cleaned up query. It selects all the GitHub repos you&amp;rsquo;ve visited from your browser history. To run it, first copy your browser history and open it in sqlite:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;cp ~/Library/Application\ Support/Google/Chrome/Default/History ~/my-history
sqlite3 ~/my-history
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, you can run this cleaned up query to see all the GitHub repos that you&amp;rsquo;ve visited.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;WITH
data1 as (select LENGTH(&amp;quot;https://github.com/&amp;quot;) as len, * from urls),
data2 as (select SUBSTR(
  url,
  len + 1,
  INSTR(SUBSTR(url, len + 1), &amp;quot;/&amp;quot;) - 1
) as user, * from data1),
data3 as (select SUBSTR(url, len + LENGTH(user) + 2) as rest, * from data2),
data4 as (select SUBSTR(rest, 0, INSTR(rest, &amp;quot;/&amp;quot;)) as repo, * from data3)

select DISTINCT
SUBSTR(url, len + 1, LENGTH(user) + 1 + LENGTH(repo)) as user_repo
from data4
where url like &amp;quot;https://github.com/%&amp;quot;
and LENGTH(repo) &amp;gt; 0
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;the-original-query&#34;&gt;The Original Query&lt;/h2&gt;
&lt;p&gt;Here is the original query, with all its messy replicated subqueries, to emphasize just how much using &lt;code&gt;WITH&lt;/code&gt; allowed me to clean this up.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT

-- Selects the user:
-- SUBSTR(
--   urls.url,
--   LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,
--   INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1
-- ) as user,

-- Selects everything after the user:
-- SUBSTR(
--   urls.url,
--   LENGTH(&amp;quot;https://github.com/&amp;quot;)
--   + LENGTH(SUBSTR(urls.url,LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1)) -- length(user)
--   + 2
-- ) as rest,

-- Selects the repo:
-- SUBSTR(SUBSTR(
--   urls.url,
--   LENGTH(&amp;quot;https://github.com/&amp;quot;)
--   + LENGTH(SUBSTR(urls.url,LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1)) -- length(user)
--   + 2
-- ), 0,
-- INSTR(SUBSTR(
--   urls.url,
--   LENGTH(&amp;quot;https://github.com/&amp;quot;)
--   + LENGTH(SUBSTR(urls.url,LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1)) -- length(user)
--   + 2
-- ), &amp;quot;/&amp;quot;)) as repo

SUBSTR(
  urls.url,
  LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,
  LENGTH(SUBSTR(
    urls.url,
    LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,
    INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1
  )) -- LENGTH(user)
  + 1 -- + 1
  + LENGTH(SUBSTR(SUBSTR(
    urls.url,
    LENGTH(&amp;quot;https://github.com/&amp;quot;)
    + LENGTH(SUBSTR(urls.url,LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1)) -- length(user)
    + 2
  ), 0,
  INSTR(SUBSTR(
    urls.url,
    LENGTH(&amp;quot;https://github.com/&amp;quot;)
    + LENGTH(SUBSTR(urls.url,LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1)) -- length(user)
    + 2
  ), &amp;quot;/&amp;quot;)))
  ) -- + LENGTH(repo)
from urls
where urls.url like &amp;quot;https://github.com/%&amp;quot;
and LENGTH(SUBSTR(SUBSTR(
    urls.url,
    LENGTH(&amp;quot;https://github.com/&amp;quot;)
    + LENGTH(SUBSTR(urls.url,LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1)) -- length(user)
    + 2
  ), 0,
  INSTR(SUBSTR(
    urls.url,
    LENGTH(&amp;quot;https://github.com/&amp;quot;)
    + LENGTH(SUBSTR(urls.url,LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1)) -- length(user)
    + 2
  ), &amp;quot;/&amp;quot;))) &amp;gt; 0  -- LENGTH(repo) &amp;gt; 0
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The two queries should produce the same results.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Facebook Messenger SQL Queries</title>
      <link>https://davidbieber.com/snippets/2020-04-12-fb-messenger-sql/</link>
      <pubDate>Sun, 12 Apr 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-04-12-fb-messenger-sql/</guid>
      
      <description>&lt;p&gt;Last week I dumped all my Facebook messenger messages into a Postgres database. I have it set up so that new messages are added the the database in real time as they are sent. Like I did in a 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-04-11-browser-history-queries&#34;&gt;previous snippet&lt;/a&gt; for analyzing my browsing history, I&amp;rsquo;ll use this snippet to sketch out some useful queries for analyzing my message history.&lt;/p&gt;
&lt;h2 id=&#34;table-schemas&#34;&gt;Table Schemas&lt;/h2&gt;
&lt;p&gt;I have two tables of messages. &lt;code&gt;messenger_archive&lt;/code&gt; contains all messages from when I first joined Facebook in August 2008 through February 2020. &lt;code&gt;messenger&lt;/code&gt; contains messages from February 2020 through now, and is updated in real time.&lt;/p&gt;
&lt;p&gt;Using the commands &lt;code&gt;\d messenger&lt;/code&gt; and &lt;code&gt;\d messenger_archive&lt;/code&gt;, I inspect the table schemas.&lt;/p&gt;
&lt;h3 id=&#34;schema-messenger&#34;&gt;Schema: messenger&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Column&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;The message content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;uid&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;A unique message id&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;author&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;The &lt;em&gt;fbid&lt;/em&gt; of the message author&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;timestamp&lt;/td&gt;
&lt;td&gt;number&lt;/td&gt;
&lt;td&gt;The timestamp in milliseconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;forwarded&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;Whether the message is a forwarded message&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;thread_id&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;A unique thread id&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;thread_type&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;GROUP or USER, indicating the thread type&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;schema-messenger_archive&#34;&gt;Schema: messenger_archive&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Column&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;sender_name&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;The message author&amp;rsquo;s name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;timestamp_ms&lt;/td&gt;
&lt;td&gt;number&lt;/td&gt;
&lt;td&gt;The timestamp in milliseconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;content&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;The message content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;type&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;One of: Payment, Call, Share, Generic, Unsubscribe, or Subscribe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;title&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;The thread title, often the name of the other participant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;is_still_participant&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;Whether I was still in the conversation at the time of the archive (Feb 2020)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;thread_type&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;One of: RegularGroup, Regular&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;thread_path&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;A unique identifier for the thread&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;schema-caveats&#34;&gt;Schema Caveats&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;messenger_archive.thread_path&lt;/code&gt; is not the same as the &lt;code&gt;messenger.thread_id&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;messenger.author&lt;/code&gt; is an integer id, whereas the &lt;code&gt;messenger_archive.sender_name&lt;/code&gt; is a string name.&lt;/li&gt;
&lt;li&gt;There may be a few overlapping messages between the two tables (?), and there may be a few messages not captured in either table.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;message-queries&#34;&gt;Message Queries&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s start sketching some useful queries.&lt;/p&gt;
&lt;h3 id=&#34;finding-links&#34;&gt;Finding Links&lt;/h3&gt;
&lt;p&gt;Listing domains from the archive:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select distinct
substring(content from &#39;.*://([^/]*)&#39;) as domain
from messenger_archive
limit 1000;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Counting unique domains:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select count(*) from (select distinct
substring(content from &#39;.*://([^/]*)&#39;) as domain
from messenger_archive) domains;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Listing links from the archive:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select distinct
substring(content from &#39;([a-z]*://[^/\s]*[a-zA-Z/]*)&#39;) as domain
from messenger_archive
limit 1000;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Counting unique links:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select count(*) from (select distinct
substring(content from &#39;([a-z]*://[^/\s]*[a-zA-Z/]*)&#39;) as domain
from messenger_archive) foo;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;email-addresses&#34;&gt;Email Addresses&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select distinct
substring(content from &#39;([a-zA-Z0-9.]+@[a-zA-Z0-9]+\.[a-zA-Z0-9]+)&#39;) as email
from messenger_archive
limit 100;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;looking-forward&#34;&gt;Looking Forward&lt;/h3&gt;
&lt;p&gt;I have a number of additional queries I&amp;rsquo;d like to write.
However, they will have to wait until a future snippet.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>More Browser History Queries</title>
      <link>https://davidbieber.com/snippets/2020-04-11-browser-history-queries/</link>
      <pubDate>Sat, 11 Apr 2020 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-04-11-browser-history-queries/</guid>
      
      <description>&lt;p&gt;
&lt;a href=&#34;https://davidbieber.com/snippets/2020-03-19-browsing-history&#34;&gt;Previously&lt;/a&gt; I listed out a few queries for poking at my browser history. Here are some more!&lt;/p&gt;
&lt;p&gt;As before, I begin by making a copy of my browsing history and opening sqlite3:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;cp ~/Library/Application\ Support/Google/Chrome/Default/History ~/my-history
sqlite3 ~/my-history
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once that&amp;rsquo;s done, we can start running the queries.&lt;/p&gt;
&lt;h2 id=&#34;youtube-videos-watched&#34;&gt;YouTube Videos Watched&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT REPLACE(urls.title, &amp;quot; - YouTube&amp;quot;, &amp;quot;&amp;quot;), urls.url
from urls
where urls.url like &amp;quot;%www.youtube.com/watch%&amp;quot;
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;youtube-search-queries&#34;&gt;YouTube Search Queries&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT REPLACE(urls.title, &amp;quot; - YouTube&amp;quot;, &amp;quot;&amp;quot;)
from urls
where urls.url like &amp;quot;%www.youtube.com/results?search_query%&amp;quot;
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;google-search-queries&#34;&gt;Google Search Queries&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT REPLACE(urls.title, &amp;quot; - Google Search&amp;quot;, &amp;quot;&amp;quot;)
from urls
where urls.url like &amp;quot;%www.google.com/search%&amp;quot; 
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;google-maps-usage&#34;&gt;Google Maps Usage&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT REPLACE(urls.title, &amp;quot; - Google Maps&amp;quot;, &amp;quot;&amp;quot;)
from urls
where urls.url like &amp;quot;%www.google.com/maps%&amp;quot; 
and urls.title != &amp;quot;Google Maps&amp;quot;
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;wikipedia-browsing-history&#34;&gt;Wikipedia Browsing History&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT REPLACE(urls.title, &amp;quot; - Wikipedia&amp;quot;, &amp;quot;&amp;quot;)
from urls
where urls.url like &amp;quot;%wikipedia.org/wiki/%&amp;quot;
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;github-users-and-orgs&#34;&gt;GitHub Users and Orgs&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT
SUBSTR(
  urls.url,
  LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,
  INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1
) as user
from urls
where urls.url like &amp;quot;https://github.com/%&amp;quot;
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The rest of the GitHub queries ended up being quite messy, so I&amp;rsquo;ve placed them at the end of the document.&lt;/p&gt;
&lt;h2 id=&#34;arxiv-papers-visited&#34;&gt;Arxiv Papers Visited&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT urls.title, REPLACE(REPLACE(urls.url, &amp;quot;.pdf&amp;quot;, &amp;quot;&amp;quot;), &amp;quot;/pdf/&amp;quot;, &amp;quot;/abs/&amp;quot;)
from urls
where urls.url like &amp;quot;https://arxiv.org/abs%&amp;quot;
or urls.url like &amp;quot;https://arxiv.org/pdf%&amp;quot;
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;hackernews-comments-read&#34;&gt;HackerNews Comments Read&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT REPLACE(urls.title, &amp;quot; | Hacker News&amp;quot;, &amp;quot;&amp;quot;), urls.url
from urls
where urls.url like &amp;quot;https://news.ycombinator.com/item%&amp;quot;
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;hackernews-posts-read&#34;&gt;HackerNews Posts Read&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT urls.title, urls.url
from visits
join visits as previous_visits on visits.from_visit == previous_visits.id
join urls on urls.id == visits.url
join urls as previous_urls on previous_urls.id == previous_visits.url
where previous_urls.url like &amp;quot;https://news.ycombinator.com%&amp;quot;
and urls.url not like &amp;quot;https://news.ycombinator.com%&amp;quot;
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;reddit-usage&#34;&gt;Reddit Usage&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT urls.title
from urls
where urls.url like &amp;quot;https://www.reddit.com/%&amp;quot;
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;reddit-links-followed&#34;&gt;Reddit Links Followed&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT urls.title, urls.url
from visits
join visits as previous_visits on visits.from_visit == previous_visits.id
join urls on urls.id == visits.url
join urls as previous_urls on previous_urls.id == previous_visits.url
where previous_urls.url like &amp;quot;%reddit.com%&amp;quot;
and urls.url not like &amp;quot;%reddit.com%&amp;quot;
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;reddit-subreddits-visited&#34;&gt;Reddit Subreddits Visited&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT
SUBSTR(
  SUBSTR(urls.url, LENGTH(&amp;quot;https://www.reddit.com/r/&amp;quot;) + 1),
  0,
  INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://www.reddit.com/r/&amp;quot;) + 1), &amp;quot;/&amp;quot;)
) as subreddit
from urls
where urls.url like &amp;quot;https://www.reddit.com/r/%&amp;quot;
order by subreddit asc
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;twitter-search-queries&#34;&gt;Twitter Search Queries&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT REPLACE(urls.title, &amp;quot; - Twitter Search / Twitter&amp;quot;, &amp;quot;&amp;quot;)
from urls
where urls.url like &amp;quot;https://twitter.com/search%&amp;quot;
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;twitter-links-followed&#34;&gt;Twitter Links Followed&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT urls.title, urls.url
from visits
join visits as previous_visits on visits.from_visit == previous_visits.id
join urls on urls.id == visits.url
join urls as previous_urls on previous_urls.id == previous_visits.url
where previous_urls.url like &amp;quot;%://t.co%&amp;quot;
and urls.url not like &amp;quot;%twitter.com%&amp;quot;
and urls.url not like &amp;quot;%://t.co%&amp;quot;
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;other-domains-visited&#34;&gt;Other Domains Visited&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT REPLACE(
SUBSTR(
  urls.url,
  INSTR(urls.url, &amp;quot;//&amp;quot;) + 2, -- strips https://
  INSTR(SUBSTR(urls.url, INSTR(urls.url, &amp;quot;//&amp;quot;) + 2), &amp;quot;/&amp;quot;) - 1
), &amp;quot;www.&amp;quot;, &amp;quot;&amp;quot;) as domain
from visits
join visits as previous_visits on visits.from_visit == previous_visits.id
join urls on urls.id == visits.url
join urls as previous_urls on previous_urls.id == previous_visits.url
where not (
     domain like &amp;quot;%goog%&amp;quot;
  or domain like &amp;quot;%t.co%&amp;quot;
  or domain like &amp;quot;%twitter.co%&amp;quot;
  or domain like &amp;quot;%wikipedia%&amp;quot;
  or domain like &amp;quot;%youtube%&amp;quot;
  or domain like &amp;quot;%github%&amp;quot;
  or domain like &amp;quot;%arxiv%&amp;quot;
  or domain like &amp;quot;%reddit%&amp;quot;
  or domain like &amp;quot;%ycombinator%&amp;quot;
  or urls.url like &amp;quot;chrome-extension://%&amp;quot;
  -- or previous_urls.url like &amp;quot;%t.co%&amp;quot;
  -- or previous_urls.url like &amp;quot;%twitter.co%&amp;quot;
  -- or previous_urls.url like &amp;quot;%goog%&amp;quot;
  -- or previous_urls.url like &amp;quot;%reddit%&amp;quot;
  -- or previous_urls.url like &amp;quot;%ycombinator%&amp;quot;
)
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&#34;using-a-different-profile&#34;&gt;Using a Different Profile&lt;/h2&gt;
&lt;p&gt;If you want to query your search history for a profile other than the default one, you can do so. E.g.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;cp ~/Library/Application\ Support/Google/Chrome/Profile\ 1/History ~/my-history
sqlite3 ~/my-history
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;messy-queries-github-repos-visited&#34;&gt;Messy Queries: GitHub Repos Visited&lt;/h2&gt;
&lt;p&gt;This query ended up being quite messy because I wasn&amp;rsquo;t able to save intermediate results as a variable. So, in order to build the query, I copied and pasted intermediate queries to reuse them. The result, with intermediate queries shown in comments, follows.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select DISTINCT

-- Selects the user:
-- SUBSTR(
--   urls.url,
--   LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,
--   INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1
-- ) as user,

-- Selects everything after the user:
-- SUBSTR(
--   urls.url,
--   LENGTH(&amp;quot;https://github.com/&amp;quot;)
--   + LENGTH(SUBSTR(urls.url,LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1)) -- length(user)
--   + 2
-- ) as rest,

-- Selects the repo:
-- SUBSTR(SUBSTR(
--   urls.url,
--   LENGTH(&amp;quot;https://github.com/&amp;quot;)
--   + LENGTH(SUBSTR(urls.url,LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1)) -- length(user)
--   + 2
-- ), 0,
-- INSTR(SUBSTR(
--   urls.url,
--   LENGTH(&amp;quot;https://github.com/&amp;quot;)
--   + LENGTH(SUBSTR(urls.url,LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1)) -- length(user)
--   + 2
-- ), &amp;quot;/&amp;quot;)) as repo

SUBSTR(
  urls.url,
  LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,
  LENGTH(SUBSTR(
    urls.url,
    LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,
    INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1
  )) -- LENGTH(user)
  + 1 -- + 1
  + LENGTH(SUBSTR(SUBSTR(
    urls.url,
    LENGTH(&amp;quot;https://github.com/&amp;quot;)
    + LENGTH(SUBSTR(urls.url,LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1)) -- length(user)
    + 2
  ), 0,
  INSTR(SUBSTR(
    urls.url,
    LENGTH(&amp;quot;https://github.com/&amp;quot;)
    + LENGTH(SUBSTR(urls.url,LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1)) -- length(user)
    + 2
  ), &amp;quot;/&amp;quot;)))
  ) -- + LENGTH(repo)
from urls
where urls.url like &amp;quot;https://github.com/%&amp;quot;
and LENGTH(SUBSTR(SUBSTR(
    urls.url,
    LENGTH(&amp;quot;https://github.com/&amp;quot;)
    + LENGTH(SUBSTR(urls.url,LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1)) -- length(user)
    + 2
  ), 0,
  INSTR(SUBSTR(
    urls.url,
    LENGTH(&amp;quot;https://github.com/&amp;quot;)
    + LENGTH(SUBSTR(urls.url,LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1,INSTR(SUBSTR(urls.url, LENGTH(&amp;quot;https://github.com/&amp;quot;) + 1), &amp;quot;/&amp;quot;) - 1)) -- length(user)
    + 2
  ), &amp;quot;/&amp;quot;))) &amp;gt; 0  -- LENGTH(repo) &amp;gt; 0
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For most of the queries on this page, you should be able to easily modify them to suit your needs.
I wouldn&amp;rsquo;t try modifying this query, though. It would be much better to build a new query from scratch using using the same technique this one was built with, than to try to modify this one to perform another task, because it would be so easy to modify something in one place but subtly miss modifying it in another location in the query that needs to also be modified.&lt;/p&gt;
&lt;p&gt;Update (April 12, 2020): I&amp;rsquo;ve now learned that you can introduce intermediate &amp;ldquo;variables&amp;rdquo; in your SQL queries, so I&amp;rsquo;ve simplified this query 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-04-12-simplifying-sql-with-with&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Tips for Effective OBS</title>
      <link>https://davidbieber.com/snippets/2020-04-11-tips-for-obs/</link>
      <pubDate>Sat, 11 Apr 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-04-11-tips-for-obs/</guid>
      
      <description>&lt;p&gt;As a newcomer to OBS, I&amp;rsquo;ve been regularly discovering new features that make my OBS experience better. Here are a handful of things I&amp;rsquo;ve found useful, that perhaps weren&amp;rsquo;t immediately obvious to me, from my early experiences with OBS.&lt;/p&gt;
&lt;h2 id=&#34;using-media-sources&#34;&gt;Using Media Sources&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;Media Source&amp;rdquo; video sources are essential when showing prerecorded video, or using a replay buffer. However, it wasn&amp;rsquo;t obvious to me how to get media sources to play their audio.&lt;/p&gt;
&lt;p&gt;When using a Media Source, here&amp;rsquo;s out to turn on the audio. In the Audio Mixer panel choose &lt;code&gt;Gear Settings &amp;gt; Advanced Audio Properties&lt;/code&gt; then set &lt;code&gt;Audio Monitoring&lt;/code&gt; to &amp;ldquo;Monitor and Output&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;namespaces-for-scenes--turning-off-the-camera&#34;&gt;Namespaces for Scenes + Turning Off the Camera&lt;/h2&gt;
&lt;p&gt;You can create multiple Profiles and Scene Collections in OBS. I only have one Profile, which I&amp;rsquo;ve named &amp;ldquo;Default&amp;rdquo; (rather than the default of &amp;ldquo;Untitled&amp;rdquo;). I made a few Scene Collections. Making new Scene Collections gives you a space to play around with new ideas for scenes and keyboard shortcuts, without disrupting the main setup(s) that you&amp;rsquo;ve put together. I like to fiddle around with new ideas in a Scene Collection I&amp;rsquo;ve named &amp;ldquo;Playground&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;If you have any sources in a Scene Collection that use your webcam, then your webcam will stay on even when it isn&amp;rsquo;t being used. If you switch to a Scene Collection with no sources using your webcam, then your webcam will turn off. I use a Scene Collection that leaves my webcam off by default, and only switch to a Scene Collection with a webcam source when I actually intend to record something that needs the webcam.&lt;/p&gt;
&lt;h2 id=&#34;replay-buffer&#34;&gt;Replay Buffer&lt;/h2&gt;
&lt;p&gt;I leave the replay buffer on in between recording scenes. By setting the replay buffer to a reasonable size like 60 seconds, I can leave it rolling without consuming too much memory (and the CPU consumption has been reasonable too, e.g. 10%). This way, if anything noteworthy happens in this period between recordings, I can still capture it.&lt;/p&gt;
&lt;h2 id=&#34;virtual-cameras&#34;&gt;Virtual Cameras&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re willing to get your hands dirty, the instructions at 
&lt;a href=&#34;https://github.com/johnboiles/obs-mac-virtualcam&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;johnboiles/obs-mac-virtualcam&lt;/a&gt; will let you use OBS as a virtual camera on Mac.&lt;/p&gt;
&lt;h2 id=&#34;transform-editing-and-scene-json-files&#34;&gt;Transform Editing and Scene &lt;code&gt;.json&lt;/code&gt; files&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;cmd-e&lt;/code&gt; opens the Scene Item Transform for a Scene Item. Using that, you can get pixel perfect positioning of any video source. You can also see and edit the json files that describe your scenes. On Mac, these scene json files can be found at &lt;code&gt;~/Library/Application Support/obs-studio/basic/scenes&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;keyboard-shortcuts&#34;&gt;Keyboard Shortcuts&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;cmd-,&lt;/code&gt; opens your settings. There&amp;rsquo;s a panel for setting keyboard shortcuts. This is a core OBS feature, and it&amp;rsquo;s extremely valuable. I really appreciate how easy OBS has made it to set up these keyboard shortcuts for switching between scenes, starting and stopping recordings, pausing and playing media, etc. I only wish I could have extra modifier keys so I could set up more shortcuts that don&amp;rsquo;t collide with the shortcuts of my IDE!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Exploring OBS and Virtual Cameras</title>
      <link>https://davidbieber.com/snippets/2020-04-09-exploring-obs/</link>
      <pubDate>Thu, 09 Apr 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-04-09-exploring-obs/</guid>
      
      <description>&lt;p&gt;This week I&amp;rsquo;ve been exploring 
&lt;a href=&#34;https://obsproject.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;em&gt;Open Broadcasting Software&lt;/em&gt; (OBS)&lt;/a&gt; and toying with using it as a virtual camera. I use a Mac, and historically there hasn&amp;rsquo;t been a good way to use OBS as a virtual camera. With 
&lt;a href=&#34;https://twitter.com/tobi&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;@tobi&lt;/a&gt;&amp;rsquo;s recent 
&lt;a href=&#34;https://github.com/obsproject/obs-studio/issues/2568&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;$10,000 bounty&lt;/a&gt; for making this a core feature, however, some developers in the OBS community leapt into action and a 
&lt;a href=&#34;https://github.com/johnboiles/obs-mac-virtualcam&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;working prototype&lt;/a&gt; of the feature was available on GitHub within days.&lt;/p&gt;
&lt;h2 id=&#34;virtual-cameras&#34;&gt;Virtual Cameras&lt;/h2&gt;
&lt;p&gt;OBS is popular software among Twitch streamers. It lets you take a bunch of video sources and rearrange them into scenes. Streamers will often overlay a camera feed of their head and a live stream of a video game, maybe with cool graphics overlaid on the whole thing.&lt;/p&gt;
&lt;p&gt;For years, OBS has let you take the scenes you create and stream them in real time to YouTube Live or Twitch or any number of other streaming services. If you wanted to use your OBS scene in Zoom or Google Meet, however, it wasn&amp;rsquo;t straightforward, at least on Mac.&lt;/p&gt;
&lt;p&gt;There were workarounds. You could project your scene to an external monitor, and then use screen sharing to share that. At times there were combinations of tools and plugins that could similarly get the job done.&lt;/p&gt;
&lt;p&gt;Now, however, it&amp;rsquo;s considerably easier. John Boiles&amp;rsquo;s has made a OBS plugin that works without fuss. For now it still requires a technical background to use, following build instructions and executing commands on the terminal to get it set up. In a matter of months, however, I expect it will make its way as a core feature into OBS.&lt;/p&gt;
&lt;h2 id=&#34;combining-obs-with-auto-video-editing&#34;&gt;Combining OBS with Auto Video Editing&lt;/h2&gt;
&lt;p&gt;As you may know, I&amp;rsquo;ve been working on 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-02-21-jump-cut-programming&#34;&gt;automatic&lt;/a&gt; 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-02-26-video-tooling-progress&#34;&gt;video&lt;/a&gt; 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-03-02-fastbook&#34;&gt;editing&lt;/a&gt; software. I&amp;rsquo;d like to be able to make quality content &amp;ndash; e.g. videos teaching interesting aspects of programming &amp;ndash; without needing to spend time on the video editing process. The cutting and rearranging would happen automatically. The music and audio adjustments would be added automatically. All I&amp;rsquo;d need to do is write a script and record the footage, and the auto editor would take care of the rest.&lt;/p&gt;
&lt;p&gt;Originally I was using Mac&amp;rsquo;s cmd-shift-5 screen capture capability to create these recordings. OBS lets you rearrange video feeds deliberately and use a variety of video sources. These video sources include window captures, cameras, and prerecorded media. The result is much more flexible than Mac&amp;rsquo;s screen capture, and so I&amp;rsquo;ve switched my auto video editing software over to use OBS for recording.&lt;/p&gt;
&lt;p&gt;As an aside, I&amp;rsquo;ve also discovered 
&lt;a href=&#34;https://obsproject.com/forum/resources/obs-ndi-newtek-ndi%E2%84%A2-integration-into-obs-studio.528/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;NDI&lt;/a&gt;, a plugin for OBS. It lets me use my phone&amp;rsquo;s camera as a video source with minimal setup. It was so easy to get working, in fact, that I&amp;rsquo;m convinced it must be a large security vulnerability to use it at all.&lt;/p&gt;
&lt;p&gt;Now that I&amp;rsquo;m using OBS to record, I enabled my auto video editing software to run automatically on any recording produced by OBS. As soon as the recording gets saved, my software starts editing it automatically (preserving the original). I&amp;rsquo;d love to have my auto editing start even sooner than that though, &lt;em&gt;before&lt;/em&gt; the recording is complete. The OBS codebase is surprisingly approachable, so I may be able to get this working.&lt;/p&gt;
&lt;h2 id=&#34;hacking-on-the-obs-codebase&#34;&gt;Hacking on the OBS Codebase&lt;/h2&gt;
&lt;p&gt;When John Boiles released the Mac Virtual Cam plugin for OBS, it was initially stuck on the wrong resolution. John told me it was hard coded to 720x480, and that was the impetus for me to poke at the code. Changing the hard coded resolution proved easy enough. Then I ran into a bug where OBS would fail to capture a window if I changed tabs in that window while OBS was closed. Though there&amp;rsquo;s inertia with entering any unfamiliar codebase, I found I was able to solve this issue for myself too. Through these two debugging experiences I got enough glimpses of the OBS plugin set up to think that OBS really is approachably hackable. I think, with hard work, I could integrate my auto editing code into OBS so that it runs in real time. It&amp;rsquo;s not the very top of my todo list for the auto video editor, but I&amp;rsquo;m excited to give this a try.&lt;/p&gt;
&lt;h2 id=&#34;replay-buffers-in-obs&#34;&gt;Replay Buffers in OBS&lt;/h2&gt;
&lt;p&gt;One neat feature in OBS is its ability to record a &amp;ldquo;replay buffer&amp;rdquo;. I have it set up to record a circular buffer of the last 60 seconds of content. That means that at any given moment, OBS has recorded the previous 60 seconds of footage. Unsaved footage older than 60 seconds is gone, but at any point, if I choose to save it, I can record the previous 60 seconds of footage.&lt;/p&gt;
&lt;p&gt;This is great because it means I can keep the camera rolling between scenes without wasting memory, and if anything noteworthy happens in that time I can capture it.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a second reason I&amp;rsquo;m excited about the replay buffer though; it may enable me to use auto-edited videos in conversations in &lt;em&gt;real time&lt;/em&gt;. I imagine the user experience like this:
I&amp;rsquo;m in a remote meeting and we&amp;rsquo;re having a discussion. By default I&amp;rsquo;m unmuted and people can hear what I&amp;rsquo;m saying. Whenever I hold down a keyboard shortcut, I&amp;rsquo;m muted in the call and OBS starts recording me. When I release the shortcut, I can continue to talk in the call. Once I&amp;rsquo;ve recorded a satisfactory amount of content for OBS, the auto-editing will be applied and I can use OBS as a virtual camera to send that recorded and edited content to my colleagues in the meeting.&lt;/p&gt;
&lt;h2 id=&#34;looking-forward&#34;&gt;Looking Forward&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m excited to become more proficient using OBS, and to explore the various plugins and overlays that streamers use with OBS. Particularly I&amp;rsquo;m excited to look into the 
&lt;a href=&#34;https://obsproject.com/forum/resources/vst-plugins.848/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;audio plugins&lt;/a&gt; that are available.&lt;/p&gt;
&lt;p&gt;I also intend to continue my auto-editing plans from before: I&amp;rsquo;m still looking forward to introducing a &amp;ldquo;script&amp;rdquo; with audio auto-transcribed and key events entered via keyboard shortcuts and auto-tracked file saves. And I still want to be able to modify this script to automatically edit the video based on the modifications.&lt;/p&gt;
&lt;p&gt;Having explored OBS for a little while now, I&amp;rsquo;m also looking forward to integrating my auto-video editing more closely with OBS, ideally resulting in real time auto editing in the end. Here&amp;rsquo;s to hoping OBS continues to feel approachably hackable!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Understanding OAuth2</title>
      <link>https://davidbieber.com/snippets/2020-03-20-understanding-oauth2/</link>
      <pubDate>Fri, 20 Mar 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-03-20-understanding-oauth2/</guid>
      
      <description>&lt;p&gt;
&lt;a href=&#34;https://oauth.net/2/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;OAuth2&lt;/a&gt; is confusing. I&amp;rsquo;ve set it up several times before, and each time I encounter it it&amp;rsquo;s a bit of a mental mess to wrap my mind around it again.&lt;/p&gt;
&lt;p&gt;So, this time, as I set up OAuth2 to let 
&lt;a href=&#34;https://davidbieber.com/projects/bieber-bot&#34;&gt;Bieber Bot&lt;/a&gt; interact with more Slack workspaces, I will write up my renewed understanding of OAuth2 in the hope that next time I have to set up OAuth2, it&amp;rsquo;s a little easier.&lt;/p&gt;
&lt;h2 id=&#34;overview-of-the-oauth2-flow&#34;&gt;Overview of the OAuth2 Flow&lt;/h2&gt;
&lt;p&gt;How does the OAuth2 flow go? Like this:&lt;/p&gt;
&lt;p&gt;The user wants to add Bieber Bot to a Slack channel. So, they&amp;rsquo;re on my website 
&lt;a href=&#34;https://davidbieber.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;(davidbieber.com)&lt;/a&gt; and they click the &lt;em&gt;Add to Slack&lt;/em&gt; button. This takes them to Slack, with GET parameters that indicate they want to add Bieber Bot to some Slack workspace. The workspace id can be part of the URL of the Add to Slack button, but even if it&amp;rsquo;s not, Slack will do the right thing and just ask the user to choose one of their workspaces. If the user isn&amp;rsquo;t already logged in to Slack, they&amp;rsquo;ll be prompted to do so at this point.&lt;/p&gt;
&lt;p&gt;After the user clicks the &lt;em&gt;Add to Slack&lt;/em&gt; button they are taken to Slack, where they are shown the list of OAuth2 scopes that Bieber Bot is requesting. If they approve giving Bieber Bot the permissions listed in the scopes, they are taken to a &lt;em&gt;redirect url&lt;/em&gt; that I, the developer of Bieber Bot, have specified. I have both pre-informed Slack of the redirect URLs I might use, and I have included a specific redirect URL in the link on the &lt;em&gt;Add to Slack&lt;/em&gt; button. When the user is redirected to this redirect url, two GET parameters are included. The first is a &lt;code&gt;code&lt;/code&gt;, which my server can use to get an Access Token / Bearer Token. The second is a &lt;code&gt;state&lt;/code&gt; which is something that I, the developer, can include on the original link from the &lt;em&gt;Add to Slack&lt;/em&gt; button in order to make sure the request I&amp;rsquo;m getting at the redirect URL is genuine.&lt;/p&gt;
&lt;p&gt;When the redirect URL is accessed with a &lt;code&gt;code&lt;/code&gt; GET parameter, it then turns around and uses that &lt;code&gt;code&lt;/code&gt; to request an Access Token from Slack. Once it has that Access Token, it tucks it away. It can use that access token in order to perform any of the permissions granted by the user during the access flow.&lt;/p&gt;
&lt;p&gt;Usually using the Access Token takes the form of issuing post requests to Slack with the Access Token as a parameter.&lt;/p&gt;
&lt;p&gt;The user can revoke access to Bieber Bot at any time. Once they do so, the Access Token becomes invalid. If Bieber Bot tries to use the Access Token at that point, it will get an error. The user will have to give Bieber Bot permissions again, and it will get a new access token, in order for it to continue providing its services and companionship.&lt;/p&gt;
&lt;h2 id=&#34;summary-of-the-the-important-bits&#34;&gt;Summary of the the Important Bits&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;User navigates from website to service (e.g. via &lt;em&gt;Add to Slack&lt;/em&gt; button).&lt;/li&gt;
&lt;li&gt;Service shows user permissions dialog.&lt;/li&gt;
&lt;li&gt;Upon accepting permissions, service redirects user back to website&amp;rsquo;s redirect URL with &lt;code&gt;code&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Website uses &lt;code&gt;code&lt;/code&gt; to get Access Token&lt;/li&gt;
&lt;li&gt;Website uses Access Token to do the stuff allowed by the permissions granted by the user&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;summary-of-the-less-important-bits&#34;&gt;Summary of the Less Important Bits&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The &lt;em&gt;Add to Slack&lt;/em&gt; button should include GET parameters for: a) &lt;code&gt;state&lt;/code&gt; so the redirect url knows the request is genuine, b) &lt;code&gt;redirect_url&lt;/code&gt; so Slack knows where to send the user after they accept the permissons, c) &lt;code&gt;scope&lt;/code&gt; indicating the permissions being requested, d) &lt;code&gt;client_id&lt;/code&gt; indicating the app (e.g. Bieber Bot) that you&amp;rsquo;re adding to Slack.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The permissions that the App can request are set up by the App ahead of time. So I think the &lt;code&gt;scope&lt;/code&gt; parameter is there if you only need to request a subset of that permissions for a particular user.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The full list of possible redirect URLs should be set up ahead of time. Then when you generate the &lt;em&gt;Add to Slack&lt;/em&gt; button, you just choose a particular redirect URL that Slack should redirect the user to after they accept the permissions. Why would you want more than one redirect URL? Well, one might be for staging, one for production, and one for local development.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The redirect URL receives both the &lt;code&gt;code&lt;/code&gt; and &lt;code&gt;state&lt;/code&gt; GET parameters. The website creating the &lt;em&gt;Add to Slack&lt;/em&gt; button decides on the state. It can then check that the state is there in the redirect URL. This prevents users from going directly to Slack without going through the website, because if they try to do that, they won&amp;rsquo;t have the state and will fail the check at the redirect URL. This is useful if you want to restrict installs for your App to specific customers, e.g. those who&amp;rsquo;ve solved a puzzle, or paid.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;what-is-this&#34;&gt;What is this?&lt;/h2&gt;
&lt;p&gt;This certainly isn&amp;rsquo;t meant to be an OAuth2 guide at all. By writing this out, I think I&amp;rsquo;ve helped myself understand the OAuth2 flow better though. That&amp;rsquo;s really what snippets are all about.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A Bit of Browser History Analysis</title>
      <link>https://davidbieber.com/snippets/2020-03-19-browsing-history/</link>
      <pubDate>Thu, 19 Mar 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-03-19-browsing-history/</guid>
      
      <description>&lt;p&gt;In a 
&lt;a href=&#34;https://davidbieber.com/snippets/2019-12-30-analyzing-my-browser-history&#34;&gt;previous snippet&lt;/a&gt; I started looking into how to analyze my browser history. Revisiting that idea tonight, I began looking into whether I might be able to infer topics of interest from my browsing history.&lt;/p&gt;
&lt;p&gt;Using my previous post as reference, I first made a copy of my browsing history:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;cp ~/Library/Application\ Support/Google/Chrome/Default/History ~/my-history
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, using sqlite3 (&lt;code&gt;sqlite3 ~/my-history&lt;/code&gt;) I began poking around.&lt;/p&gt;
&lt;p&gt;This query allowed me to pull up all my YouTube video views:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select visits.id, urls.title, urls.url
from visits
join urls on urls.id == visits.url
where urls.url like &amp;quot;%www.youtube.com/w%&amp;quot;
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And this query gave me my Google Search history:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select visits.id, urls.title
from visits
join urls on urls.id == visits.url
where urls.url like &amp;quot;%www.google.com/search%&amp;quot; 
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This one gave me my Wikipedia browsing history:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;select distinct urls.title 
from visits
join urls on urls.id == visits.url
where urls.url like &amp;quot;%wikipedia.org/wiki/%&amp;quot;
limit 50;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I think it will be useful to bring in the contents of the URLs too, not just the title and url string, for determining topics of interest. Even without that, my Google Search history, YouTube history, and Wikipedia history are already an interesting start.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Principles of Pico</title>
      <link>https://davidbieber.com/snippets/2020-03-14-principles-of-pico/</link>
      <pubDate>Sat, 14 Mar 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-03-14-principles-of-pico/</guid>
      
      <description>&lt;p&gt;Here&amp;rsquo;s an attempt at capturing and organizing my thoughts on Pico, from our conversation about it March.&lt;/p&gt;
&lt;p&gt;First, an attempt at an overview of the Pico system.&lt;/p&gt;
&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;
&lt;p&gt;You enter cards through a variety of sources. You can enter cards manually, like flash cards. You can also import cards from your note taking software. Cards can also be created from your contacts list.&lt;/p&gt;
&lt;p&gt;Then, Pico shows you these cards in an Anki-meets-Tinder swipe-based spaced repetition manner. You get a stack of cards, and each card presents you with a suggested action you should take:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reengage with idea X from your notes&lt;/li&gt;
&lt;li&gt;Reach out to person Y from your contacts&lt;/li&gt;
&lt;li&gt;Read a passage from book Z&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can choose to perform the action on the card, swiping right. Or you can ignore the card and get the next one on the stack by swiping left. The app automatically learns which cards are good to show you. Ideally it helps you to read more, to reengage with your own ideas over time, and to keep in touch with your friends.&lt;/p&gt;
&lt;p&gt;Lots of things to like about this! I&amp;rsquo;m now going to take a stab at separating out the goals of Pico, the mechanism of Pico, and the specific tasks that Pico targets today.&lt;/p&gt;
&lt;h2 id=&#34;distilling-the-principles-of-pico&#34;&gt;Distilling the Principles of Pico&lt;/h2&gt;
&lt;p&gt;The goals are noble. At a high level, Pico aims to help you spend less time on addictive websites with infinite scroll, and more time doing things that matter to you. I applaud anything that sets out to help you reclaim your attention.&lt;/p&gt;
&lt;p&gt;I think mentally it helps to separate the mechanism of managing attention that Pico provides from the specific tasks it helps its users to achieve.&lt;/p&gt;
&lt;p&gt;The mechanism seems to operate around these three principles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;offloaded memory&lt;/li&gt;
&lt;li&gt;entropy injection (offloaded decision making)&lt;/li&gt;
&lt;li&gt;spaced repetition&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The specific tasks it helps with are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;brainstorming / reengaging with old ideas&lt;/li&gt;
&lt;li&gt;(re)connecting with people&lt;/li&gt;
&lt;li&gt;studying&lt;/li&gt;
&lt;li&gt;reading&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, the mechanism is general enough that other specific tasks can easily be slotted in as cards in the Pico system.&lt;/p&gt;
&lt;h2 id=&#34;thoughts&#34;&gt;Thoughts!&lt;/h2&gt;
&lt;p&gt;Alright, stop me if I&amp;rsquo;ve misrepresented Pico so far. Let me tell you what I think about it.&lt;/p&gt;
&lt;h3 id=&#34;general-purposeness&#34;&gt;General Purposeness&lt;/h3&gt;
&lt;p&gt;I think Pico has some really solid ideas underlying it. Particularly I find the idea of using spaced repetition to reengage with your ideas quite compelling.
The idea of using cards to dive into passages of books is also appealing.&lt;/p&gt;
&lt;p&gt;Using spaced repetition to reengage with your friends seems a tricky thing to get right, since it risks dehumanizing the relationships without special care taken both by the developer (you) and the user of the system.&lt;/p&gt;
&lt;p&gt;Each of these different types of cards seems like it comes with lots of room for domain specific tailoring. For example, if a card represents a passage of a book, the user may want to quickly dive into the full book (not just the passage), and then to create a new card at the end of their reading session so they can continue reading from where they left off later.
If a card represents an idea from my notes, I&amp;rsquo;d like to be able to read the surrounding notes in my note taking software, where I&amp;rsquo;m best able to engage with the ideas.&lt;/p&gt;
&lt;p&gt;Getting each of these domains right in a single app (or through clean interactions with other systems) seems like a difficult challenge, but potentially quite rewarding if done well.&lt;/p&gt;
&lt;h3 id=&#34;data-entry&#34;&gt;Data Entry&lt;/h3&gt;
&lt;p&gt;I expect the usability of Pico will be a big part of what makes the Pico experience pleasant or not. Data entry and the whole card creation process seems like one of the tricky things to get right. If I want to create cards for studying, based on my notes, then I&amp;rsquo;ll want to be taking those notes in some other software (unless you&amp;rsquo;re also building a Roam / RemNote competitor too!). Going from this other software into Pico can be challenging because there are many possible &amp;ldquo;other softwares&amp;rdquo; that people could be coming from and many possible formats people could be taking notes in.&lt;/p&gt;
&lt;p&gt;For the book reading case, the experience I would want would be that when I&amp;rsquo;m reading a PDF or eBook a card is automatically created for each book I&amp;rsquo;ve opened, that is automatically kept up to date with the part of the book that I&amp;rsquo;m up to.&lt;/p&gt;
&lt;h3 id=&#34;overwhelmed-by-cards&#34;&gt;Overwhelmed by Cards&lt;/h3&gt;
&lt;p&gt;This thought comes from my inexperience with spaced-repetition software systems. It seems like with traditional spaced repetition algorithms, it can be easy to get overwhelmed by a backlog of cards to review if you take a few days (or heavens forbid a week!) off of review.&lt;/p&gt;
&lt;p&gt;Lately I&amp;rsquo;ve been doing spaced repetition in Roam Research using an adhoc system I threw together for myself using Browserflow. Instead of having specific days on which to review cards, they get reviewed in a specific review session. If I skip a day, all future review sessions just come a day later; the backlog doesn&amp;rsquo;t grow.&lt;/p&gt;
&lt;h3 id=&#34;motivation&#34;&gt;Motivation&lt;/h3&gt;
&lt;p&gt;Pico is a method for spending your time with intention. This is fantastic!&lt;/p&gt;
&lt;p&gt;My understanding of the &amp;ldquo;Principles of Pico&amp;rdquo; are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Spend less time on things you don&amp;rsquo;t want to be doing (Facebook, Twitter, etc)&lt;/li&gt;
&lt;li&gt;Spend more time on things you do want&lt;/li&gt;
&lt;li&gt;Use external mechanisms and automation to guide you toward these good uses of time&lt;/li&gt;
&lt;li&gt;Use gamification to increase time spent on these productive uses of time&lt;/li&gt;
&lt;li&gt;Learn from experience what works and what doesn&amp;rsquo;t&lt;/li&gt;
&lt;li&gt;Reengage with your own ideas using spaced repetition&lt;/li&gt;
&lt;li&gt;Reengage with people using spaced repetition&lt;/li&gt;
&lt;li&gt;Learn things via spaced repetition&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;m 100% on board with these principles and am very excited to see where Pico lands a year from now.&lt;/p&gt;
&lt;p&gt;Heads up that I wrote most of this snippet back on March 14, 2020, and then only finished it up and published it today December 20, 2020. So, forgive the delay and let&amp;rsquo;s continue the conversation some time in the next ten months.&lt;/p&gt;
&lt;p&gt;Cheers.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Fastbook: Listen to Audiobooks Faster</title>
      <link>https://davidbieber.com/snippets/2020-03-02-fastbook/</link>
      <pubDate>Mon, 02 Mar 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-03-02-fastbook/</guid>
      
      <description>&lt;p&gt;Aaron Mayer 
&lt;a href=&#34;https://medium.com/100audiobooks/the-100-audiobook-challenge-terms-and-conditions-455c7e9409aa&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;aims to listen to 100 audiobooks in a single month&lt;/a&gt;. He intends to listen to these audiobooks at 2x - 3x speed. Intense!&lt;/p&gt;
&lt;p&gt;For the last few weeks, I&amp;rsquo;ve been working on 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-02-21-jump-cut-programming/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;automatic video&lt;/a&gt; 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-02-26-video-tooling-progress/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;editing tools&lt;/a&gt;. And one of the core features I&amp;rsquo;ve been working with is 
&lt;a href=&#34;https://github.com/carykh/jumpcutter/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;automatic speed adjustments to videos&lt;/a&gt; to eliminate silent airtime and make the videos more engaging. This seems like a perfect fit for Aaron&amp;rsquo;s challenge.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve adapted this tooling into a new tool I&amp;rsquo;m calling 
&lt;a href=&#34;https://gist.github.com/dbieber/98f909640773b5b0a0fe5696da369a1b&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Fastbook&lt;/a&gt;. It accepts audiobooks in the form of &lt;code&gt;.wav&lt;/code&gt; files, and can apply speed adjustments to the silence and the spoken word independently, even removing silence entirely if desired.&lt;/p&gt;
&lt;p&gt;If Aaron can already comfortably (with great focus) listen to a book at 2.5x speed, he can listen to a 10 hour book in 4 hours. If 20% of that book is actually silence, then the 10 hour book becomes an 8 hour book with silence removed, and the total listen time drops to just 3h12. I think 20% may actually be a conservative estimate for silent time, though it will vary from narrator to narrator.&lt;/p&gt;
&lt;p&gt;Estimating 45 minutes saved per book, this tool can save over 3 days total time across 100 books. Or, alternatively, Aaron could drop the playback speed down from 2.5x to 2x without increasing his total listening time at all, but potentially helping out his comprehension substantially.&lt;/p&gt;
&lt;p&gt;This tool won&amp;rsquo;t be appropriate for all audiobook listeners. For many, the silences matter, and removing them would degrade the quality of the book. For many, listening at 2.5x would also degrade the quality of the book. So use this tool with caution.&lt;/p&gt;
&lt;p&gt;For those of you who are intersted, however, here&amp;rsquo;s how to use Fastbook.&lt;/p&gt;
&lt;h2 id=&#34;installing-fastbook&#34;&gt;Installing Fastbook&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve made Fastbook available for free on GitHub. You can 
&lt;a href=&#34;https://gist.github.com/dbieber/98f909640773b5b0a0fe5696da369a1b&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;access it here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To use it, save it to your computer as &lt;code&gt;fastbook.py&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Next, make sure you have all the dependencies installed. See the dependencies section for what is required.&lt;/p&gt;
&lt;h2 id=&#34;pre-work-converting-your-book-to-wav&#34;&gt;Pre-work: Converting Your Book to &lt;code&gt;.wav&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;You need your audiobook in wav format to use Fastbook.&lt;/p&gt;
&lt;p&gt;To convert an audiobook to wav, use 
&lt;a href=&#34;https://www.ffmpeg.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;ffmpeg&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Install ffmpeg. Then, run &lt;code&gt;ffmpeg -i book.aax book.wav&lt;/code&gt; to convert an Audible audiobook to a wav file. There may be an additional step if your aax file is DRM protected.&lt;/p&gt;
&lt;h2 id=&#34;using-fastbook&#34;&gt;Using Fastbook&lt;/h2&gt;
&lt;p&gt;Now you can use Fastbook like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;python fastbook.py \
--audio_path=/path/to/book.wav \
--output_path=/path/to/book-fast.wav \
--loud_speed=1 \
--quiet_speed=5
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;--audio_path&lt;/code&gt; should point to an existing wav file that you downloaded or generated in the pre-work section. &lt;code&gt;--output_path&lt;/code&gt; is the path to the file that Fastbook will generate. Finally, &lt;code&gt;--loud_speed&lt;/code&gt; is how much to speed up the normal spoken text of the book by, and &lt;code&gt;--quiet_speed&lt;/code&gt; is how much to speed up the silence in the book by. You can remove silence by setting &lt;code&gt;--quiet_speed=99999&lt;/code&gt; or any other similarly large number.&lt;/p&gt;
&lt;h3 id=&#34;dependencies&#34;&gt;Dependencies&lt;/h3&gt;
&lt;p&gt;Here are the dependencies you need to use Fastbook.&lt;/p&gt;
&lt;p&gt;First, you need &lt;strong&gt;Python 3&lt;/strong&gt;. You can follow 
&lt;a href=&#34;https://realpython.com/installing-python/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;these instructions&lt;/a&gt; to set up Python 3 if you don&amp;rsquo;t already have it installed.&lt;/p&gt;
&lt;p&gt;Then, you need these Python dependencies: &lt;em&gt;fire&lt;/em&gt;, &lt;em&gt;scipy&lt;/em&gt;, &lt;em&gt;tqdm&lt;/em&gt;, &lt;em&gt;numpy&lt;/em&gt;, and &lt;em&gt;audiotsm&lt;/em&gt;. Install these with &lt;code&gt;pip install fire scipy tqdm numpy audiotsm&lt;/code&gt; or use your favorite Python package manager.&lt;/p&gt;
&lt;p&gt;Finally, to do the pre-work, you will likely need ffmpeg. Installation instructions are available 
&lt;a href=&#34;https://www.ffmpeg.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;read-quick&#34;&gt;Read quick!&lt;/h2&gt;
&lt;p&gt;I recommend for Aaron to use the default speed settings of &lt;code&gt;--loud_speed=1 --quiet_speed=5&lt;/code&gt;. This won&amp;rsquo;t eliminate the silence entirely, but will reduce the audio time considerably. Then, for the remaining speed-up, I suggest using whatever media player you were already using, such as VLC which supports arbitrary speed adjustments in real time. Hpy rdng!&lt;/p&gt;
&lt;h2 id=&#34;demo&#34;&gt;Demo&lt;/h2&gt;
&lt;p&gt;This blog post, narrated slowly:&lt;/p&gt;
&lt;p&gt;&lt;audio
controls
src=&#34;https://davidbieber.com/audio/fastbook.m4a&#34;&gt;
Your browser does not support the &lt;code&gt;audio&lt;/code&gt; element.
&lt;/audio&gt;&lt;/p&gt;
&lt;p&gt;This blog post again, now with just the silence accelerated:&lt;/p&gt;
&lt;p&gt;&lt;audio
controls
src=&#34;https://davidbieber.com/audio/fastbook-fast.m4a&#34;&gt;
Your browser does not support the &lt;code&gt;audio&lt;/code&gt; element.
&lt;/audio&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Video Tooling Progress</title>
      <link>https://davidbieber.com/snippets/2020-02-26-video-tooling-progress/</link>
      <pubDate>Wed, 26 Feb 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-02-26-video-tooling-progress/</guid>
      
        <message>Progress on automatic video editing, including &#39;Auto Auto-Jumpcutter&#39;, &#39;Auto-Commit&#39;, and Keyboard Shortcuts.</message>
      
      <description>&lt;p&gt;Over the last week and a half I&amp;rsquo;ve been making screen recordings of myself programming. Mostly what I&amp;rsquo;ve been programming is tooling to help myself make better screen recordings. Here&amp;rsquo;s an overview of what I&amp;rsquo;ve put together so far.&lt;/p&gt;
&lt;h2 id=&#34;auto-auto-jumpcutter&#34;&gt;Auto Auto-Jumpcutter&lt;/h2&gt;
&lt;p&gt;This springboards directly from carykh&amp;rsquo;s 
&lt;a href=&#34;https://github.com/carykh/jumpcutter&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;jumpcutter&lt;/a&gt; project, which uses 
&lt;a href=&#34;https://www.ffmpeg.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;ffmpeg&lt;/a&gt; and AudioTSM to speed up the silent sections of a video. Auto Auto-Jumpcutter has two &amp;ldquo;auto&amp;quot;s in its name because jumpcutter already does automatic jumpcutting of videos, and Auto Auto-Jumpcutter uses 
&lt;a href=&#34;https://pythonhosted.org/watchdog/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;watchdog&lt;/a&gt; to automatically apply jumpcutter the moment a screen recording is captured.&lt;/p&gt;
&lt;p&gt;The result is that my typing appears superhuman in speed, but slows down while I&amp;rsquo;m speaking, without me needing to do any manual editing to the video to achieve this effect.&lt;/p&gt;
&lt;h2 id=&#34;auto-commit&#34;&gt;Auto-Commit&lt;/h2&gt;
&lt;p&gt;I also made for myself a git auto-committer. Every time I save a file during a screen recording session, the change is immediately and automatically committed. The commit message is selected automatically from the diff. The result is that I have a timestamped log of all changes made during the recording. This is super useful for editing the recordings (both automatically and manually) because I can pinpoint exactly where in the recording any change took place. It also works hand-in-hand with the next piece of tooling.&lt;/p&gt;
&lt;h2 id=&#34;keyboard-shortcuts&#34;&gt;Keyboard Shortcuts&lt;/h2&gt;
&lt;p&gt;Just using Auto Auto-Jumpcutter goes a long way toward having automatically edited videos, but it doesn&amp;rsquo;t completely eliminate the need for manual editing.
For example, it provides no way to do multiple takes and stitch together the good parts of each. For this I&amp;rsquo;ve set up a keyboard shortcut system for myself using the Python 
&lt;a href=&#34;https://pypi.org/project/keyboard/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;keyboard&lt;/a&gt; module. This way I can indicate via keyboard shortcuts to remove a selection of footage during the recording session, and have it automatically be removed during the automatic editing phase. This last step &amp;ndash; using the keyboard shortcuts to guide automatic editing &amp;ndash; is an active work in progress.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Jump-Cut Programming: Take 1</title>
      <link>https://davidbieber.com/snippets/2020-02-21-jump-cut-programming/</link>
      <pubDate>Fri, 21 Feb 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-02-21-jump-cut-programming/</guid>
      
        <message>Inspired by @realCarykh, I jump-cut into the world of automatic video editing.</message>
      
      <description>&lt;p&gt;I&amp;rsquo;ve been toying around with recording myself programming. Here&amp;rsquo;s a clip.&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/OxsuHWVtMSM&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;In this clip I use 
&lt;a href=&#34;https://davidbieber.com/projects/python-fire&#34;&gt;Python Fire&lt;/a&gt; to create a simple two-function calculator. Nothing special about that.&lt;/p&gt;
&lt;p&gt;What is special is that the programming has automatically been sped up by 
&lt;a href=&#34;https://github.com/carykh/jumpcutter&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;carykh/jumpcutter&lt;/a&gt;, and that I&amp;rsquo;ve used 
&lt;a href=&#34;https://zulko.github.io/moviepy/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;moviepy&lt;/a&gt; to set the programming to the music 
&lt;a href=&#34;http://incompetech.com/music/royalty-free/index.html?isrc=USUAN1100414&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&amp;ldquo;Dangerous&amp;rdquo;&lt;/a&gt;, a clip I got from 
&lt;a href=&#34;https://www.youtube.com/audiolibrary/music&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;YouTube&amp;rsquo;s free Audio Library&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;lessons-learned-from-take-1&#34;&gt;Lessons Learned from &amp;ldquo;Take 1&amp;rdquo;&lt;/h2&gt;
&lt;h3 id=&#34;what-worked-well&#34;&gt;What worked well?&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;External Monitor&lt;/strong&gt;: I purchased an external monitor. This made a huge difference. Now I can manage video-editing tools, a terminal, a browser, etc on one screen, while keeping the contents of the video (the editor and public terminal) on the other screen and recording it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;
&lt;a href=&#34;https://github.com/carykh/jumpcutter&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;carykh/jumpcutter&lt;/a&gt;&lt;/strong&gt;: This tool can automatically speed up the silent parts of a video, resulting in shorter less-boring videos.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mac Screen Capture&lt;/strong&gt;: cmd-shift-5 lets you capture video on Mac. You can choose what directory the captured video is saved to. Before I discovered this, I used QuickTime, but this is easier to use.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Using 
&lt;a href=&#34;https://pythonhosted.org/watchdog/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;watchdog&lt;/a&gt;&lt;/strong&gt; This is a Python module that can monitor your filesystem and trigger an action when files are created or modified. I use it to a) automatically rename video files as they&amp;rsquo;re created, and b) to automatically apply jumpcutting to new captured videos. The filename format I use is &lt;code&gt;YYYY-MM-DD-screen-recording-###.mov&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Python Fire&lt;/strong&gt;: The first twenty clips I recorded (not released) were all of me building the tooling I now use as I record videos. Most of this tooling lives in Python Fire CLIs. These CLIs let me do things like composite audio, perform auto-jumpcutting, and rename videos.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;things-to-improve&#34;&gt;Things to improve:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Zoom in!&lt;/strong&gt; The code is blurry and small and the video as is needs to be watched at 1080p to look OK, which is silly.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Audio Quality&lt;/strong&gt; I have a lapel mic I&amp;rsquo;m using for new recordings and it helps.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Storytelling&lt;/strong&gt; Is a Python Fire CLI for adding and subtracting the most compelling story? I think there&amp;rsquo;s room for improvement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Manual Editing&lt;/strong&gt; I did no manual editing for the clip above. I think for quality videos, however, learning to do some manual editing is going to be essential. We&amp;rsquo;ll see how far my inclination to automate everything takes me first though.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;I&amp;rsquo;m really enjoying this process of recording videos. And more than making the videos, I&amp;rsquo;m enjoying building the software to help me make the videos. Next step for me is getting more familiar with moviepy. And Davinci Resolve. But one thing at a time.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The Future-Predicting Game Show Host</title>
      <link>https://davidbieber.com/snippets/2020-02-08-future-gameshow-host/</link>
      <pubDate>Sat, 08 Feb 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-02-08-future-gameshow-host/</guid>
      
        <message>A game show host reveals 2 boxes. In box A is either $1 million or $0, in box B there is $1000. You won&#39;t believe what&#39;s inside Box A!</message>
      
      <description>&lt;p&gt;A game show host reveals 2 boxes, box A and box B. In box A is either $1 million or $0, in box B there is $1000.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;re told, choose either just box A or both A and B.&lt;/p&gt;
&lt;p&gt;You keep the contents of the boxes you choose.
Also, the host knows what box you will choose, and has placed $1 million in A if you will choose only A, and $0 in A if you will choose both A and B.&lt;/p&gt;
&lt;p&gt;Some contestants, faced with this choice, would choose both A and B. They reason that since the money has already been placed, choosing A and B is guaranteed to yield $1000 more than choosing just A.
Others would choose only A, since per the host&amp;rsquo;s plans this option leads to a significantly better payout.&lt;/p&gt;
&lt;p&gt;Clearly choosing only A is $1000 worse than choosing both A and B, yet choosing A only is allegedly better given the host&amp;rsquo;s foresight. These statements appear contradictory, and this situation is known as 
&lt;a href=&#34;https://en.wikipedia.org/wiki/Newcomb%27s_paradox&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Newcomb&amp;rsquo;s Paradox&lt;/a&gt;.
How can we reconcile these two true but contradictory statements?&lt;/p&gt;
&lt;p&gt;We do so by clarifying:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Right now&lt;/em&gt; choosing only A is $1000 worse than choosing both A and B.&lt;/li&gt;
&lt;li&gt;However, having a brain&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;em&gt;at the time the money is placed&lt;/em&gt; that will lead you to choose only A at the time of choosing gives the $1 million outcome.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Is this something you have control over? Can you &lt;em&gt;decide&lt;/em&gt; at the time the money is placed to have a brain that will lead you to later choose only box A?&lt;/p&gt;
&lt;p&gt;Yes.&lt;/p&gt;
&lt;p&gt;It may seem like &lt;em&gt;no&lt;/em&gt;, for a few reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You didn&amp;rsquo;t even know there was a choice to make.&lt;/li&gt;
&lt;li&gt;You surely don&amp;rsquo;t get to make choices about how your brain works, right?&lt;/li&gt;
&lt;li&gt;Since the host is able know your choice ahead of time, that must mean it&amp;rsquo;s predetermined, right?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;However, none of these reasons are entirely valid.&lt;/p&gt;
&lt;p&gt;First, it&amp;rsquo;s true that at the time the money is placed, you didn&amp;rsquo;t necessarily know you had a choice to make. You hadn&amp;rsquo;t yet been informed that you would later be on this game show. However, it&amp;rsquo;s possible you considered the situation as a hypothetical anyway (maybe while reading a blog post, for instance). It isn&amp;rsquo;t necessary that you considered precisely the situation that you would later find yourself in, only that you&amp;rsquo;ve given conscious deliberate thought to the way you make choices. By thinking this through, you can decide now whether you have a brain that would later choose box A or one that would later choose both A and B, should the game show situation ever arise.&lt;/p&gt;
&lt;p&gt;Next, you absolutely do get to make choices about how your brain works. You can choose when to sleep, when to study, what substances to ingest, and most importantly, what to focus your attention on. All of these levers are yours to pull, and they all affect how your brain will operate in the future.&lt;/p&gt;
&lt;p&gt;At the time you choose the boxes, it&amp;rsquo;s still your decision as to which box(es) to choose. (In the sense that it&amp;rsquo;s your brain that produces the decision.)
But you must have been predictable, at least to the host, for them to have predicted what choice you would later make.
(Nothing wrong with being predictable!)&lt;/p&gt;
&lt;p&gt;How is it that you were predictable? Does this require determinism?
One extreme way you may have been predictable is if the host knows exactly how events will play out, right down to the thoughts you will have and the choices you will make.&lt;/p&gt;
&lt;p&gt;It doesn&amp;rsquo;t have to be &lt;em&gt;quite&lt;/em&gt; so extreme though. The host only claimed to have roughly one bit of information about you and the future: what binary choice you would make when confronted with the box dilemma. That doesn&amp;rsquo;t require omniscience. The host may have no idea what the weather is going to be the next day, as long as they&amp;rsquo;re able to predict whether or not you&amp;rsquo;re taking box B.&lt;/p&gt;
&lt;p&gt;So maybe they know a little about how your mind works, or they&amp;rsquo;ve read something you&amp;rsquo;ve posted online that lets them conclude how you will handle the box situation.&lt;/p&gt;
&lt;p&gt;You must consider that whatever they know, they knew it at the time that they chose how to fill the boxes. (They likely also knew it at the time they chose to host the game show in the first place.)&lt;/p&gt;
&lt;p&gt;What I think is most likely is that this host does know precisely how you think about this choice. They do this by understanding to a very high degree of precision how your brain is going to cope with the decision of which boxes to choose. Think of the host as a very skilled poker player, that can read you like a book. Instead of just knowing whether you&amp;rsquo;re bluffing or not, they know what you&amp;rsquo;re going to think 
&lt;a href=&#34;https://www.ncbi.nlm.nih.gov/pubmed/6640273&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;before you even think it&lt;/a&gt;. It&amp;rsquo;s like weather forecasting, but instead of understanding the atmosphere, they&amp;rsquo;re understanding you.&lt;/p&gt;
&lt;p&gt;And like with weather forecasting, their model is imperfect. It&amp;rsquo;s good enough to know what box you&amp;rsquo;ll choose, with certainty, but only because that only requires forecasting a small window (a week, let&amp;rsquo;s say) into the future. Like the atmospheric conditions that determine the weather, your brain is a chaotic system. Any imperfection in the model, however small, will eventually blow up and lead to large errors in the model in the future. So our host can&amp;rsquo;t model your every thought a year into the future, let alone e.g. the whole population&amp;rsquo;s behaviors.&lt;/p&gt;
&lt;p&gt;So what boxes should you choose?&lt;/p&gt;
&lt;p&gt;You should choose to open just box A. By reaching this conclusion (and more importantly, by adopting the strategy for reasoning that leads to this conclusion), you guarantee yourself $1 million the next time you encounter a wealthy generous time traveling game show host interested in philosophy and mathematics.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I say &amp;ldquo;brain&amp;rdquo;, but I really mean the whole of your situation and life circumstances. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>A Mostly-Complete List of Bieber Bot&#39;s Capabilities</title>
      <link>https://davidbieber.com/snippets/2020-02-04-bieber-bot-capabilities/</link>
      <pubDate>Tue, 04 Feb 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-02-04-bieber-bot-capabilities/</guid>
      
        <message>A snapshot of Bieber Bot&#39;s many many capabilities.</message>
      
      <description>&lt;p&gt;
&lt;a href=&#34;https://davidbieber.com/projects/bieber-bot&#34;&gt;Bieber Bot&lt;/a&gt; has an ever-growing list of capabilities. I&amp;rsquo;ve tried to capture that complete list here. Feel free to use 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-01-25-ask-me-anywhere&#34;&gt;Ask Me Anywhere&lt;/a&gt; to inquire about any of these features and leave some contact info if you&amp;rsquo;d like me to get in touch.&lt;/p&gt;
&lt;h2 id=&#34;timer-triggered-capabilities&#34;&gt;Timer-triggered capabilities:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Greetings, encouragement, and love!&lt;/li&gt;
&lt;li&gt;Piano and violin reminders&lt;/li&gt;
&lt;li&gt;Screen time monitoring&lt;/li&gt;
&lt;li&gt;Reminders to reconnect with old friends&lt;/li&gt;
&lt;li&gt;Reminders to exercise&lt;/li&gt;
&lt;li&gt;Is now a good time to do laundry?&lt;/li&gt;
&lt;li&gt;GoodReads updates&lt;/li&gt;
&lt;li&gt;FocusMate session planning&lt;/li&gt;
&lt;li&gt;TODOs of various kinds (&lt;em&gt;TODO&lt;/em&gt;, &lt;em&gt;tonight&lt;/em&gt;, &lt;em&gt;tomorrow&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Reminders of the importance of eating soon after waking up&lt;/li&gt;
&lt;li&gt;Facebook event tracking&lt;/li&gt;
&lt;li&gt;Assert Baton reminders&lt;/li&gt;
&lt;li&gt;Exercise Baton reminders&lt;/li&gt;
&lt;li&gt;Tweeting scheduled Tweets&lt;/li&gt;
&lt;li&gt;Transaction logging&lt;/li&gt;
&lt;li&gt;Yearly payroll tracking&lt;/li&gt;
&lt;li&gt;After work activity planning and reminders&lt;/li&gt;
&lt;li&gt;After work activity suggestions when nothing is already planned&lt;/li&gt;
&lt;li&gt;Sleep reminders&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;chat-triggered-capabilities&#34;&gt;Chat-triggered capabilities:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Sending messages between David and Adriana&lt;/li&gt;
&lt;li&gt;Violin, Piano, and Exercise tracking&lt;/li&gt;
&lt;li&gt;Food suggestions&lt;/li&gt;
&lt;li&gt;Suggests people or activities&lt;/li&gt;
&lt;li&gt;Assert Baton and Exercise Baton passing&lt;/li&gt;
&lt;li&gt;Baton status checking&lt;/li&gt;
&lt;li&gt;Budget status checking (Why is this not on a timer too?)&lt;/li&gt;
&lt;li&gt;Get BieberBot&amp;rsquo;s version number&lt;/li&gt;
&lt;li&gt;Play Jeopardy (individually or against Adriana)&lt;/li&gt;
&lt;li&gt;Play Jeopardy in Croatian (individually or against Adriana)&lt;/li&gt;
&lt;li&gt;Add financial transaction details&lt;/li&gt;
&lt;li&gt;Add TODOs&lt;/li&gt;
&lt;li&gt;Send or schedule Tweets&lt;/li&gt;
&lt;li&gt;Log activities&lt;/li&gt;
&lt;li&gt;ACK! Any ol&#39; text back to you (Great conversationalist!)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;other-capabilities&#34;&gt;Other capabilities:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Logs financial transactions (triggered by credit-card swipes)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think that&amp;rsquo;s all! May have missed some, and there are more planned, but this is a mostly-comprehensive list as of Feb 4, 2020.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What&#39;s Next for Ask Me Anywhere?</title>
      <link>https://davidbieber.com/snippets/2020-01-26-next-steps-for-ama/</link>
      <pubDate>Sun, 26 Jan 2020 10:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-01-26-next-steps-for-ama/</guid>
      
        <message>My next steps for Ask Me Anywhere.</message>
      
      <description>&lt;p&gt;Yesterday I put up an early version of 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-01-25-ask-me-anywhere/&#34;&gt;Ask Me Anywhere&lt;/a&gt;. You&amp;rsquo;ll notice it&amp;rsquo;s in the snippets section of the website, rather than part of the main blog. This gives me the freedom to post it even though I know it&amp;rsquo;s not as polished as it could be.&lt;/p&gt;
&lt;p&gt;Now that this first pass is published, it&amp;rsquo;s time to start thinking about where to go next with Ask Me Anywhere.&lt;/p&gt;
&lt;h2 id=&#34;short-term-stylistic-improvements&#34;&gt;Short Term: Stylistic Improvements&lt;/h2&gt;
&lt;p&gt;On mobile, the &amp;ldquo;Click to React&amp;rdquo; text shows up and is improperly styled. I didn&amp;rsquo;t intend for it to show up at all. On certain mobile devices and browsers, it seems there are even larger issues than this, such as double tapping sometimes not working at all. Let me know if it doesn&amp;rsquo;t work with your browser so I can fix it.&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;Click to React&amp;rdquo; text also sometimes causes the flow of the text to change, which interrupts the reading experience somewhat. I would like to fix this so that the text flow is never changed by the presence of this message.&lt;/p&gt;
&lt;p&gt;I also would like to tweak the styling to minimize the friction someone feels in deciding to leave a message. I think adding a question-mark icon, which when moused-over gives an explanation of why this feature is there in the first place could be useful. This could strike a good balance between being non-intrusive and letting people know that their thoughts are warmly welcomed.&lt;/p&gt;
&lt;h2 id=&#34;longer-term-socratic-tutorials&#34;&gt;Longer Term: &amp;ldquo;Socratic Tutorials&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;Ask Me Anywhere&amp;rdquo; is really an MVP that came out of a larger idea: &amp;ldquo;Socratic Tutorials&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;My idea is that a &lt;em&gt;Socratic Tutorial&lt;/em&gt; is a blog post structured in a very particular way. It begins with a brief introduction to a topic, followed by a series of questions you might want to ask about that topic. Click a question to reveal an answer to that question, followed by additional questions you might have about the topic. In this way, you can explore the contents of the post in the order that best suits your interests. I also hope that by having to click questions to view the answers, it will help motivate what you&amp;rsquo;re reading, since you&amp;rsquo;ll be actively wondering about the question when you read the response.&lt;/p&gt;
&lt;p&gt;If a reader of a &lt;em&gt;Socratic Tutorial&lt;/em&gt; doesn&amp;rsquo;t understand something, or has a question that isn&amp;rsquo;t already addressed, they can choose to ask that question. The author can then add it to the list of questions available during reading if they choose to do so. In that way, &amp;ldquo;Ask Me Anywhere&amp;rdquo; is almost a subset of the features planned for Socratic Tutorials.&lt;/p&gt;
&lt;p id=&#34;cbp_example&#34;&gt;
My very first blog post ever was about &lt;a href=&#34;https://davidbieber.com/post/2012-09-04-collapsible-blog-posts/&#34;&gt;Collapsible Blog Posts&lt;/a&gt;. The premise was that you could click on a paragraph, and it would be replaced with a summary of that paragraph. This paragraph is an example; click on it, and it will be replaced with a summary.
&lt;/p&gt;
&lt;p id=&#34;_cbp_example&#34;&gt;
This was a
&lt;a href=&#34;https://davidbieber.com/post/2012-09-04-collapsible-blog-posts/&#34;&gt;Collapsible Blog Post&lt;/a&gt; paragraph. Click to un-collapse.
&lt;/p&gt;
&lt;p&gt;I learned early on from this experiment that the reverse process actually is more useful. Present the user with a short summary, and let them click if they want to read additional details.&lt;/p&gt;
&lt;p id=&#34;cbp_reverse&#34;&gt;
Here&#39;s an example of a short paragraph that you can click to reveal additional details.
&lt;/p&gt;
&lt;p id=&#34;_cbp_reverse&#34;&gt;
The reason it makes more sense to show the summary first is that it empowers the user to choose how to spend their time. If they are interested in understanding more about a topic, they can choose to expand the paragraph and read the details. If instead they read the extended paragraph first, there isn&#39;t much value to them also reading the summarized version. And if they just want the summarized version, having them see the full version first isn&#39;t too useful either.
&lt;/p&gt;
&lt;p&gt;In some ways the idea for &amp;ldquo;Socratic Tutorials&amp;rdquo; is a spiritual descendent of Collapsible Blog Posts. They both share a goal: give the user control over the information they&amp;rsquo;re consuming, as they&amp;rsquo;re reading. Socratic Tutorials and Ask Me Anywhere take an additional step though, giving the user the ability to communicate directly with the author while they&amp;rsquo;re reading.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll likely have noticed that this post uses &amp;ldquo;Ask Me Anywhere&amp;rdquo;. That means you can double click any paragraph, or click between two paragraphs, in order to send a note directly to the author.
I hope you do this, as I&amp;rsquo;d love to hear any thoughts you may have.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Ask Me Anywhere</title>
      <link>https://davidbieber.com/snippets/2020-01-25-ask-me-anywhere/</link>
      <pubDate>Sat, 25 Jan 2020 10:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-01-25-ask-me-anywhere/</guid>
      
        <message>In this post you can ask a question at _any_ point.</message>
      
      <description>&lt;p&gt;With this post, I&amp;rsquo;m demoing a new work-in-progress feature for my blog called &amp;ldquo;Ask Me Anywhere&amp;rdquo;.
The feature lets you leave a comment or ask a question at &lt;em&gt;any&lt;/em&gt; point while reading my writing.
The goal is to encourage readers to respond to my writing, because I&amp;rsquo;m interested in having a conversation and hearing what you have to say.&lt;/p&gt;
&lt;p&gt;You can try it right now. Either &lt;strong&gt;double click&lt;/strong&gt; (double-tap on mobile) on any paragraph, or click between two paragraphs, to open a comment box. Enter your thoughts, click submit, and &lt;em&gt;voila!&lt;/em&gt;, comment submitted.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;re welcome to enter your email address, name, Twitter handle, Facebook ID, or any other form of contact info if you&amp;rsquo;d like me to respond. And if you do, there is high likelihood that I will respond. If you don&amp;rsquo;t, you&amp;rsquo;re anonymous, and you certainly won&amp;rsquo;t receive a private response.&lt;/p&gt;
&lt;p&gt;Comments and questions that you submit are not posted publicly anywhere. This isn&amp;rsquo;t a comments section for public discussion. If you want to discuss my posts publicly, submit them on Hacker News or Reddit, or head to Twitter to engage. While this website isn&amp;rsquo;t the place for public discussions&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, I am curious to know about such a discussion if it&amp;rsquo;s happening. So, feel free to let me know about such a discussion via &amp;ldquo;AMA&amp;rdquo; if you&amp;rsquo;re starting one.&lt;/p&gt;
&lt;p&gt;What happens when you leave a comment? This part&amp;rsquo;s still a work in progress, but ideally my digital personal assistant 
&lt;a href=&#34;https://davidbieber.com/projects/bieber-bot&#34;&gt;Bieber Bot&lt;/a&gt; will notify me of the new comment at the next convenient time. If there are many comments coming in, Bieber Bot will try to be smart about batching the notifications together, and so the notification may be delayed, but I&amp;rsquo;ll soon read your message.&lt;/p&gt;
&lt;p&gt;For now, Ask Me Anywhere is only activated for this one post. Once I&amp;rsquo;ve tested it out a bit, and perhaps made some changes, I&amp;rsquo;m hoping to then activate it for the 
&lt;a href=&#34;https://davidbieber.com/posts&#34;&gt;rest of my posts&lt;/a&gt; 
&lt;a href=&#34;https://davidbieber.com/snippets&#34;&gt;and snippets&lt;/a&gt; as well. So I&amp;rsquo;m particularly keen to get feedback early so I can iterate and improve it soon. Give it a try, let me know what you think. You know how to reach me!&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re interested in learning more about the internals, the source is 
&lt;a href=&#34;https://github.com/dbieber/davidbieber.com/blob/772b5dd87da532357a1cdf04a8caa027268bfbac/hugo/assets/js-src/ask-me-anywhere.jsx&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;available on GitHub&lt;/a&gt;. Feel free to have a poke around.&lt;/p&gt;
&lt;p&gt;The name of the project &amp;ndash; &amp;ldquo;Ask Me Anywhere&amp;rdquo; &amp;ndash; reflects my intention to enable readers to ask questions as they&amp;rsquo;re reading. However, I welcome all types of reactions: questions, comments, feedback, corrections, new ideas, etc. I look forward to hearing what you have to say.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Update (Dec 2022): You can now also use the Discussion feature! Ever since 
&lt;a href=&#34;https://davidbieber.com/snippets/2022-06-21-using-discord/&#34;&gt;this snippet&lt;/a&gt; there are now public discussions directly on my website. Give it a try today! &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>How much time has humanity spent on different areas of science?</title>
      <link>https://davidbieber.com/snippets/2020-01-24-time-spent-on-science/</link>
      <pubDate>Fri, 24 Jan 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-01-24-time-spent-on-science/</guid>
      
      <description>&lt;p&gt;How much time has humanity, collectively, spent researching physics?&lt;/p&gt;
&lt;p&gt;What about chemistry? Neuroscience? Algorithms? (etc&amp;hellip;)&lt;/p&gt;
&lt;p&gt;How has this rate of study changed over time?
How much of it is duplicate work (e.g. two nations or organizations independently working toward the same milestones before sharing their findings)?&lt;/p&gt;
&lt;p&gt;What fraction of this is done by professors, post docs, PhD students, etc?&lt;/p&gt;
&lt;p&gt;Particularly in the last 100 years, what have these numbers been?&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m interested in visualizing some of these metrics, because I think they would be useful for putting the work that I see happening around me in machine learning and in neuroscience into perspective. I also think this data would tell a fascinating story.&lt;/p&gt;
&lt;p&gt;For example, one plot that I think would be compelling would be person-hours-per-year spent thinking about physics plotted as a function of time over the last 100 years, with important physics milestones shown on the same plot (e.g. as a 
&lt;a href=&#34;https://medium.com/berkeleyischool/how-to-create-a-visualization-showing-events-on-time-series-data-in-excel-96abbc1475e0&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;time series plot with events&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;One worry with such a visualization is that the population is growing rapidly, and so the interesting story of how humanity&amp;rsquo;s attention has shifted between fields over time may be lost to a visualization that simply shows population growth. It may be necessary to normalize by population to tell such a story.&lt;/p&gt;
&lt;p&gt;It may seem infeasible to precisely collect this data, as there is no public registry of who is thinking about what. However, I think the data is perhaps more readily available than appears at first blush.&lt;/p&gt;
&lt;p&gt;Where would the data come from?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Search trends&lt;/li&gt;
&lt;li&gt;University enrollments&lt;/li&gt;
&lt;li&gt;Publication counts&lt;/li&gt;
&lt;li&gt;Surveys&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Search trends are of course a more recent source of data, only going back one or two decades. The pre-1990s version of search trends might be library records, or book sales.&lt;/p&gt;
&lt;p&gt;University enrollments and degrees granted tells a significant story about how many people are studying different areas. You can roughly estimate how much time a student majoring in physics puts into their studies, and if course enrollments are available that estimate can be even more precise.&lt;/p&gt;
&lt;p&gt;Scientific fields make their mark on the world by publishing their research. Counting publications can provide an estimate of one piece of humanity&amp;rsquo;s effort studying science.&lt;/p&gt;
&lt;p&gt;Finally, for contemporary data, and maybe even a little historical data, one could uses surveys / polling techniques to estimate where scientific mindshare is going today.&lt;/p&gt;
&lt;p&gt;Among this data I&amp;rsquo;d be curious to see when historically there have been large swings in mindshare toward a particular topic. Right now, anecdotally, machine learning research is engaging a quickly increasing number of people, including drawing people away from other fields. I&amp;rsquo;d love to see this anecdotal evidence backed up (or refuted) by data. And I expect there are plenty of similar historical precidents that I would be quite interested in learning more about as well.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t foresee collecting this data or performing these visualizations myself in the near future. This post is just an opportunity to think aloud, not a plan for my own action. But if you have data like this, or know of someone who has done a related analysis, I&amp;rsquo;d be quite interested to hear about it. Don&amp;rsquo;t hesitate to get in touch.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Say One Thing Well</title>
      <link>https://davidbieber.com/snippets/2020-01-14-say-one-thing-well/</link>
      <pubDate>Tue, 14 Jan 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-01-14-say-one-thing-well/</guid>
      
      <description>&lt;p&gt;Blog posts written by amateurs are often interesting and entertaining; they can offer perspectives not seen elsewhere. However, they often fall into the trap of trying to do too much. The best blog posts do one thing, and do it well. If you&amp;rsquo;re writing a blog post, you should choose a single, narrow point that you want to make, and make it well.&lt;/p&gt;
&lt;p&gt;While this may seem like obviously good advice, in practice the temptation to broaden the scope of a blog post can be very real. So it is important to actively practice discretion in limiting the scope of any post.&lt;/p&gt;
&lt;p&gt;How does scope creep come about? Authors may have a temptation to write about tangentially related topics. Sometimes this will be in order to provide justification or context. Other times the author simply has multiple lessons on the same topic they wish to share.&lt;/p&gt;
&lt;p&gt;Any one of these scenarios will lead the author to increase the scope of their writing. Even in the face of these situations, however, it is important to keep a narrow scope.&lt;/p&gt;
&lt;p&gt;In this post, for example, the core message is that &amp;ldquo;when writing a blog post, you should have a narrowly scoped thesis.&amp;rdquo; It is tempting for me to then also write about how to choose that thesis. After all, this seems a natural discussion to have while explaining the importance of a narrow scope. However, this would be a dangerous move, because a good discussion about how to choose a thesis well requires giving advice like &amp;ldquo;ask yourself: what are you interested in and knowledgeable about?&amp;rdquo;, and &amp;ldquo;think about what your audience is likely to care about&amp;rdquo;, etc. These suggestions don&amp;rsquo;t help make the core point, that your scope should be exceedingly narrow.&lt;/p&gt;
&lt;p&gt;In writing this post, it is tempting to write about how &amp;ldquo;trying to do too much can lead to doing multiple things poorly&amp;rdquo; applies in other, non-writing, contexts too. This has the potential to be an insightful discussion. However, this would only serve to detract from the main point: in &lt;em&gt;writing blog posts specifically&lt;/em&gt;, you should choose a single main point and make it well. Trying to broaden this to other contexts would weaken the argument, because the wider the context is, the more exceptions there are. If I had said &amp;ldquo;in all of life, do one thing and do it well&amp;rdquo;, people would correctly protest: that&amp;rsquo;s no way to live a life, you should aim to be well-rounded. So, I strengthen my argument by narrowing its scope: in writing a blog post, pick a single thesis and defend it convincingly.&lt;/p&gt;
&lt;p&gt;Why is it important to have just one main point? To start, having a single well defined main point improves the clarity of your writing. It is easier to be persuasive when you have a well-defined objective you are trying to impress upon your readers. Stray too far from this main point and it distracts the reader and weakens your piece.&lt;/p&gt;
&lt;p&gt;In the age of online writing and sharing, the importance of a single clear thesis is increased. Having a well-scoped piece increases its sharability. There is no risk that the recipient of the shared article will mistake the reason for its sharing. Having a well-scoped piece also makes it easier to reference that piece in the future. One can simply link to the article if they want to leverage its argument, rather than needing to specify &amp;ldquo;in the third section of David&amp;rsquo;s piece on online writing&amp;hellip;&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Additionally readers have limited time and attention. So, don&amp;rsquo;t bury the lead. Don&amp;rsquo;t make readers have to dig deep to uncover a point that can be stated succinctly. Show your readers your respect for their time and attention by making your point immediately clear. Then they can make an informed choice about whether they&amp;rsquo;d like to learn more. It&amp;rsquo;s their time. Don&amp;rsquo;t trick them with ambiguous or click-bait headlines. Let them invest it well by telling them upfront what it is you want to convince them of.&lt;/p&gt;
&lt;p&gt;Of course there are exceptions to the rule. For educational pieces, teaching a curriculum of topics, it may be appropriate to have multiple lessons. And if you&amp;rsquo;re writing for literary value, then the core takeaway may not be the central reason for your writing. In the general case though, critical for the vast majority of blogs being written today, it is wise to stick to a single thesis. State it clearly and defend it well.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;ve learned just one thing from this article, it&amp;rsquo;s that the best articles should leave you with just one thing to learn.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Writing Assistant Tool Idea</title>
      <link>https://davidbieber.com/snippets/2020-01-13-writing-tool-idea/</link>
      <pubDate>Mon, 13 Jan 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-01-13-writing-tool-idea/</guid>
      
        <message>A structured question-asking tool may be useful for writing effectively.</message>
      
      <description>&lt;h3 id=&#34;background-writing-is-hard&#34;&gt;Background: Writing is Hard&lt;/h3&gt;
&lt;p&gt;Sometimes I find writing feels easy &amp;ndash; e.g. when 
&lt;a href=&#34;https://davidbieber.com/snippets/2019-12-30-writing-for-no-audience/&#34;&gt;writing for no audience&lt;/a&gt;, when writing something you&amp;rsquo;ve already thought extensively about, when telling a story in a logical order that you&amp;rsquo;re deeply familiar with. Other times, I find writing very difficult.&lt;/p&gt;
&lt;p&gt;When I&amp;rsquo;m writing a paper, I am writing explicitly for an audience, the story is not always clear immediately, and the material is something I&amp;rsquo;m becoming familiar with over time, not something about which I&amp;rsquo;m already deeply familiar.
So, I find paper writing hard.&lt;/p&gt;
&lt;p&gt;I have an idea that I think will help me write more effectively. It&amp;rsquo;s a software tool that structures the time you spend writing. I&amp;rsquo;ll describe the tool, but I don&amp;rsquo;t anticipate building it. Perhaps we can come up with a low-resource version of this idea, e.g. with paper and pencil, that I can try even without building this tool.&lt;/p&gt;
&lt;h3 id=&#34;the-writing-system&#34;&gt;The Writing System&lt;/h3&gt;
&lt;p&gt;The tool presents you with a prompt, a textbox, and a timer.&lt;/p&gt;
&lt;p&gt;The initial prompt is &amp;ldquo;What do you want to write about?&amp;rdquo;, and the initial timer is for 5 minutes. Subsequent prompts will be determined from what you&amp;rsquo;ve entered in the past.&lt;/p&gt;
&lt;p&gt;In the textbox, you are encouraged to respond to the prompt.&lt;/p&gt;
&lt;p&gt;As part of your response, you can issue some commands / keywords.
If you start a line with &lt;code&gt;!&lt;/code&gt; or &lt;code&gt;?&lt;/code&gt;, then that line will get used as a future prompt.
You can specify the relative importance of a future prompt by including a priority.
This will determine the order in which you are presented with the prompts.
E.g. &lt;code&gt;!0&lt;/code&gt; is highest priority, and so such a line will become the next prompt you receive, unless there are other priority 0 prompts already queued up.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;! &amp;lt;topic&amp;gt;&lt;/code&gt; is short for &amp;ldquo;&amp;lt;topic&amp;gt; is a topic I want to write about later&amp;rdquo;
&lt;code&gt;? &amp;lt;question&amp;gt;&lt;/code&gt; is short for &amp;ldquo;&amp;lt;question&amp;gt; is a question I want to answer later&amp;rdquo;&lt;/p&gt;
&lt;p&gt;There should also be a way to indicate &amp;ldquo;&amp;lt;topic&amp;gt; is a topic I&amp;rsquo;ll need to do more research on&amp;rdquo;, and then for one of the prompts to be about spending time researching a topic, rather than writing about it. Then the next prompt may be to write about what you just learned in the research section.&lt;/p&gt;
&lt;p&gt;Other available commands include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:pause&lt;/code&gt; to stop the timer&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:unpause&lt;/code&gt; to start the timer again&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:extend&lt;/code&gt; to add additional time to the timer&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:next&lt;/code&gt; to skip to the next prompt&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The system is easily extensible, so a writer with a programming background can easily add new commands, or modify the logic that determines when prompts are shown and when breaks are taken. A programming-proficient writer will also have programmatic access to everything they write, as well as the corresponding prompts and metadata.&lt;/p&gt;
&lt;p&gt;Once the timer reaches 0, a short break is initiated, and then the next prompt is revealed.&lt;/p&gt;
&lt;p&gt;The idea is to move quickly, and get all your thoughts onto the page, without getting bogged down in a DFS traversal of information about a single line of the overall text.&lt;/p&gt;
&lt;h3 id=&#34;additional-details&#34;&gt;Additional details&lt;/h3&gt;
&lt;p&gt;Every keystroke is logged, so if you write something, and then switch to a new version of it, you will still be able to see the original version. No need to worry about pasting in a password though, since the keylogging data is readily accessible in a plaintext format and you can edit it directly e.g. if anything sensitive does leak in.&lt;/p&gt;
&lt;p&gt;This system has a decent amount of overlap with the 
&lt;a href=&#34;https://davidbieber.com/projects/shh-shell&#34;&gt;shh shell&lt;/a&gt; project that I&amp;rsquo;ve already built,
and perhaps a version of this new idea could be easily added to the shh shell. Alternatively, the shh-shell could be forked to build this new system.&lt;/p&gt;
&lt;p&gt;Calendar integration would be cool, so that it times your prompts nicely if you have a meeting coming up so you get to a good break point in time for your meeting.&lt;/p&gt;
&lt;h3 id=&#34;implementation-thoughts&#34;&gt;Implementation Thoughts&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;d like to build this onto an existing text editor, rather than writing my own. E.g. using Google Docs would be good.
However, the disadvantage of this is that it makes the keystroke logging feature more difficult. Fortunately, Google Docs does have good history tracking. Google Docs also provides good programmatic access. So, an agent running in the background while you write could be taking periodic snapshots too. Such an agent could also be extracting the commands and prompts you write.&lt;/p&gt;
&lt;p&gt;However, it wouldn&amp;rsquo;t be able to execute the commands immediately, the way shh shell does. For some commands this may be a real disadvantage.&lt;/p&gt;
&lt;p&gt;I also like the idea of the agent giving the prompts being Bieber Bot &amp;ndash; that is, being the same &lt;em&gt;being&lt;/em&gt; as my personal digital assistant. I can picture it asking me &amp;ldquo;you&amp;rsquo;ve been writing continuously for over an hour; is it time for a break?&amp;rdquo; or &amp;ldquo;it looks like you stopped writing abruptly there, did you get distracted?&amp;rdquo;.&lt;/p&gt;
&lt;h3 id=&#34;initial-experimentation&#34;&gt;Initial Experimentation&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve been trying the idea out in a low-tech way (manually timing things, manually looking up what the next prompt should be).&lt;/p&gt;
&lt;p&gt;Here is the main issue I&amp;rsquo;ve seen so far in the first half hour of testing. When the time runs out for a prompt, I&amp;rsquo;m still in the middle of the prompt. I&amp;rsquo;ve usually started expounding on some idea relevant to the prompt, and there are actually several ideas remaining that I haven&amp;rsquo;t even started exploring for the prompt yet. So what should have happened / what should I do next time? Maybe I could have done a higher level discussion of the prompt and made new future sub-prompts along the way. Or at the end of a section, I could have the system give me a bit of time to create sub-prompts of things I&amp;rsquo;d like to address in the section but didn&amp;rsquo;t get to.&lt;/p&gt;
&lt;p&gt;I could see having a limited time to create new prompts be a good forcing function for coming up with structured high level thinking after a moderate amount of time of lower level writing. So in my next round of testing, I&amp;rsquo;ll try this, and continue to iterate on the idea.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Learning by Teaching in Online Education</title>
      <link>https://davidbieber.com/snippets/2020-01-09-learning-by-teaching/</link>
      <pubDate>Thu, 09 Jan 2020 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-01-09-learning-by-teaching/</guid>
      
        <message>One of the best ways to learn is to teach.</message>
      
      <description>&lt;p&gt;Long ago (2013) I spent a summer interning at Khan Academy.
Also long ago (2014) 
&lt;a href=&#34;https://twitter.com/harvest_zhang&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Harvest&lt;/a&gt; and I built a tool for creating educational videos online, in the browser (
&lt;a href=&#34;https://davidbieber.com/projects/teach-everyone&#34;&gt;Teach Everyone&lt;/a&gt;; warning, bit rot ahead).&lt;/p&gt;
&lt;p&gt;Today, I want to see these two methodologies combined.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I want it to become common practice that after you spend significant time learning something online, you make a quick-and-dirty video explaining what you just learned.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;the-vision&#34;&gt;The Vision&lt;/h3&gt;
&lt;p&gt;Imagine you&amp;rsquo;ve just completed a series of organic chemistry lessons on Khan Academy. The KA website pops up a modal recommending that you &amp;ldquo;Make a video teaching what you learned to help solidify your understanding of Organic Chemistry!&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;You click through to a browser based video creation tool &amp;ndash; a cross between Google Slides, Illustrator / Teach Everyone, and OBS / a video editor.
In minutes, you&amp;rsquo;re able to assemble a video teaching the material you&amp;rsquo;ve spent the last hours or days wrapping your head around.&lt;/p&gt;
&lt;p&gt;You combine text, images, drawings, video, and audio to create your video. And when you&amp;rsquo;re done, you have the option to save it privately, share it on YouTube or social media, or to make it visible to others studying the same subject.&lt;/p&gt;
&lt;h3 id=&#34;benefits&#34;&gt;Benefits&lt;/h3&gt;
&lt;p&gt;There are two main benefits from this approach.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You get to learn by teaching.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Teaching is a super effective way to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reinforce the material so that you remember it longer&lt;/li&gt;
&lt;li&gt;Help you notice gaps in your understanding and fill them in&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So by preparing this little video after spending all that time learning, you&amp;rsquo;ll be left with a better and longer lasting understanding of the material.&lt;/p&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Others can learn from &lt;em&gt;you&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Often times the best teachers are those who remember what it&amp;rsquo;s like not to understand. Since you&amp;rsquo;ve just gone through the process of learning the material, you know exactly which parts were difficult to grasp and what it took for you to grasp them. So your video may end up helping others more than the KA videos in some cases!&lt;/p&gt;
&lt;h3 id=&#34;video-creation-tool&#34;&gt;Video Creation Tool&lt;/h3&gt;
&lt;p&gt;This post isn&amp;rsquo;t a design doc, but I will briefly sketch out what I imagine for the video creation tool.&lt;/p&gt;
&lt;p&gt;The main interface is a video preview above a timeline, similar to what you would see in Davinci Resolve or any professional video editing tool. You additionally have the option to create clips.&lt;/p&gt;
&lt;p&gt;You can create clips from text, images, KA-style drawings, audio, or video. Importantly, you can record audio and video clips, or create a KA-style drawing, directly in your browser.&lt;/p&gt;
&lt;p&gt;Once you&amp;rsquo;ve created some clips, you can position them both in time (on the timeline), and in space (on the video preview).&lt;/p&gt;
&lt;p&gt;I intend to write more about the details of this vision for video creation tool at a later point, but for now the most important thing about it is that it prioritizes being quick to use over being fully featured and professional, and that it can be used directly in the browser. This way it can be used by online learners as part of their online learning experience.&lt;/p&gt;
&lt;h3 id=&#34;additional-notes&#34;&gt;Additional Notes&lt;/h3&gt;
&lt;p&gt;My main premise is that students, young and old, should have a light-weight way to create educational videos immediately after learning something online.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve framed this discussion around a hypothetical tool for students to use on Khan Academy, but it applies equally well to educational videos on YouTube and elsewhere. 
&lt;a href=&#34;https://davidbieber.com/projects/teach-everyone&#34;&gt;Teach Everyone&lt;/a&gt; was an early prototype showing that you can create Khan Academy style animated drawings (i.e. virtual writing on a blackboard) with accompanying audio directly in the browser. Since then, Teach Everyone has suffered some bit rot and unfortunately isn&amp;rsquo;t operational today. However, I&amp;rsquo;m hopeful that some new project will step up, and provide an even better in-browser experience for educational video creation. And then beyond that, I&amp;rsquo;m hopeful that this tool becomes common place for students to use as part of their everyday online learning routine.&lt;/p&gt;
&lt;p&gt;If you want to discuss these ideas, don&amp;rsquo;t hesitate to get in touch: &lt;a href=&#34;mailto:david810+learning-by-teaching@gmail.com&#34;&gt;david810+learning-by-teaching@gmail.com&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What does &#34;Ordinary&#34; mean in Ordinary Least Squares?</title>
      <link>https://davidbieber.com/snippets/2020-01-08-ordinary-least-squares/</link>
      <pubDate>Wed, 08 Jan 2020 02:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-01-08-ordinary-least-squares/</guid>
      
        <message>It means the standard method. Nothing fancy.</message>
      
      <description>&lt;p&gt;&amp;ldquo;Ordinary Least Squares&amp;rdquo; regression, or OLS for short, is a method for finding a best-fit line, given a set of data points. When people refer to linear regression without additional context or qualifiers, they&amp;rsquo;re probably referring to ordinary least squares regression.&lt;/p&gt;
&lt;p&gt;So, what does &amp;ldquo;ordinary&amp;rdquo; mean in this context? Is it a mathematical term with a precise technical meaning?&lt;/p&gt;
&lt;p&gt;Well, no. In this case &amp;ldquo;ordinary&amp;rdquo; means exactly what you might expect: standard, vanilla, lacking any bells and whistles. Since least squares regression is so common, there are lots of variants. Weighted Least Squares (in which each data point is given its own weight) is a such a variant. So, in OLS, the O for ordinary simply means we&amp;rsquo;re not referring to one of these variants.&lt;/p&gt;
&lt;p&gt;What about &amp;ldquo;ordinary differential equations&amp;rdquo; (ODEs)? What does ordinary refer to there?&lt;/p&gt;
&lt;p&gt;In that context, ordinary refers to ordinary derivatives, as opposed to partial derivatives. So again, it&amp;rsquo;s not a mathematical term like a reference to ordinal numbers.&lt;/p&gt;
&lt;p&gt;In both cases, ordinary seems to take on its ordinary English definition &amp;ndash; its OED, if I may.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>pyd-swyt; cf-bh-din</title>
      <link>https://davidbieber.com/snippets/2020-01-02-pyd-swyt-cf-bh-din/</link>
      <pubDate>Thu, 02 Jan 2020 02:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-01-02-pyd-swyt-cf-bh-din/</guid>
      
        <message>This is my life motto.</message>
      
      <description>&lt;h3 id=&#34;pyd-swyt-cf-bh-din&#34;&gt;pyd-swyt; cf-bh-din&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s pronounced just like it&amp;rsquo;s spelled (&amp;ldquo;pied, swite, cuff, buh-din&amp;rdquo;). It&amp;rsquo;s my life motto.
And I think these are good principles to live by. Here they are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Pursue your dreams.&lt;/li&gt;
&lt;li&gt;Say what you think.&lt;/li&gt;
&lt;li&gt;Cultivate friendships.&lt;/li&gt;
&lt;li&gt;Be happy.&lt;/li&gt;
&lt;li&gt;Do it now.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I think each of these is self-explanatory. Briefly though, let&amp;rsquo;s consider each.&lt;/p&gt;
&lt;h3 id=&#34;pursue-your-dreams&#34;&gt;Pursue Your Dreams&lt;/h3&gt;
&lt;p&gt;Work toward long term goals you think are worthwhile.
It&amp;rsquo;s easy to fall into the trap of chasing promotions and paychecks, so the &amp;ldquo;pyd&amp;rdquo; in pyd-swyt serves as a reminder to never lose sight of your dreams.&lt;/p&gt;
&lt;h3 id=&#34;say-what-you-think&#34;&gt;Say What You Think&lt;/h3&gt;
&lt;p&gt;It can be easier to go along with the status quo than to voice dissent.
It can be easier to assume others are correct than to voice confusion.
Usually though, it is better to express your dissent / confusion / support.
The &amp;ldquo;swyt&amp;rdquo; in pyd-swyt serves as a constant reminder to speak your mind, especially when it would be more comfortable not to do so.&lt;/p&gt;
&lt;h3 id=&#34;cultivate-friendships&#34;&gt;Cultivate Friendships&lt;/h3&gt;
&lt;p&gt;Reach out to people you care about, and to people you want to know better.
Reconnect with those you haven&amp;rsquo;t seen in a long time, rather than losing touch with them gradually.
Time spent with friends is time well-spent, so the &amp;ldquo;cf&amp;rdquo; in &amp;ldquo;cf-bh-din&amp;rdquo; stands as a reminder to cultivate friendships.&lt;/p&gt;
&lt;h3 id=&#34;be-happy&#34;&gt;Be Happy&lt;/h3&gt;
&lt;p&gt;Do the things you love, and do them often.
Spend time with the people you care about.
Do what makes you happy.
Don&amp;rsquo;t sacrifice these things for your other values.
&amp;ldquo;bh&amp;rdquo;; be happy.&lt;/p&gt;
&lt;h3 id=&#34;do-it-now&#34;&gt;Do It Now&lt;/h3&gt;
&lt;p&gt;These are principles for now.
Don&amp;rsquo;t wait to pursue your dreams.
Don&amp;rsquo;t wait to say what you think.
Don&amp;rsquo;t wait to cultivate friendships.
Certainly don&amp;rsquo;t wait to be happy.
Do each of these things every day, starting now.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What to do in Moments of Internet Addiction</title>
      <link>https://davidbieber.com/snippets/2020-01-02-moments-of-internet-addiction/</link>
      <pubDate>Thu, 02 Jan 2020 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-01-02-moments-of-internet-addiction/</guid>
      
        <message>A brainstorming of potential activities to help combat mild internet addiction.</message>
      
      <description>&lt;p&gt;I often feel addicted to YouTube, TV shows, browsing HackerNews, or social media.
When I do, I&amp;rsquo;m tempted to just keep scrolling or watching, and I can waste hours on the internet.
Afterward, and even during, I may feel an inclination to stop, but I continue consuming content anyway.
It feels unhealthy, and I generally regret when I spend my time this way.
For some reason, I do it anyway though, and so I think of this habit like an addiction.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re like me and fall into these unhealthy attention-consuming rabbit holes, here is a list of things we can do instead of continuing the addictive behavior.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Nothing; doing &lt;em&gt;nothing&lt;/em&gt; is a perfectly valid option.&lt;/li&gt;
&lt;li&gt;Say hi to a friend.&lt;/li&gt;
&lt;li&gt;Call home.&lt;/li&gt;
&lt;li&gt;Write.&lt;/li&gt;
&lt;li&gt;Go for a walk.&lt;/li&gt;
&lt;li&gt;Read a book.&lt;/li&gt;
&lt;li&gt;Monologue.&lt;/li&gt;
&lt;li&gt;Think.&lt;/li&gt;
&lt;li&gt;Make plans for the future.&lt;/li&gt;
&lt;li&gt;Evaluate HALT (hungry? angry? lonely? tired?)&lt;/li&gt;
&lt;li&gt;Evaluate 
&lt;a href=&#34;https://davidbieber.com/snippets/2020-01-02-pyd-swyt-cf-bh-din&#34;&gt;pyd-swyt; cf-bh-din&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I&amp;rsquo;m 
&lt;a href=&#34;https://davidbieber.com/snippets/2019-12-30-analyzing-my-browser-history&#34;&gt;toying with&lt;/a&gt; the idea of getting Bieber Bot to notice when I&amp;rsquo;m exhibiting addictive behavior. If I can get that working, I&amp;rsquo;d love for Bieber Bot to notice when I&amp;rsquo;m addicted to YouTube, Hacker News, or Twitter and suggest one of the above activities for me to perform instead.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>2020 Resolutions</title>
      <link>https://davidbieber.com/snippets/2020-01-01-new-years-resolutions/</link>
      <pubDate>Mon, 30 Dec 2019 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2020-01-01-new-years-resolutions/</guid>
      
        <message>In which I set concrete resolution for 2020.</message>
      
      <description>&lt;p&gt;I&amp;rsquo;ve set New Year&amp;rsquo;s Resolutions most years for the last several years. Let&amp;rsquo;s review:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Resolution&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;td&gt;Play violin on 100 days&lt;/td&gt;
&lt;td&gt;Played on 43 days&lt;/td&gt;
&lt;td&gt;&lt;font color=&#34;maroon&#34;&gt;Nope&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2018&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2017&lt;/td&gt;
&lt;td&gt;Longer arms&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;font color=&#34;green&#34;&gt;Yesssss!&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2016&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2015&lt;/td&gt;
&lt;td&gt;Exercise 200 days&lt;br&gt; Read 200 days&lt;/td&gt;
&lt;td&gt;Exercise: 200 days by summer&lt;br&gt; Reading: (look this up)&lt;/td&gt;
&lt;td&gt;Yes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2014&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2013&lt;/td&gt;
&lt;td&gt;100 days of push ups&lt;/td&gt;
&lt;td&gt;145 done by December&lt;/td&gt;
&lt;td&gt;&lt;font color=&#34;green&#34;&gt;Yes!&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The missing entries I don&amp;rsquo;t recall or have readily available, but I had goals in those years too.&lt;/p&gt;
&lt;p&gt;This year, I add a new resolution to the table:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Resolution&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;Communicate publicly 100 times&lt;/td&gt;
&lt;td&gt;**Finger&amp;rsquo;s crossed**&lt;/td&gt;
&lt;td&gt;TBD!&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;What counts as &amp;ldquo;communicating publicly&amp;rdquo;?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A 
&lt;a href=&#34;https://davidbieber.com/snippets&#34;&gt;snippet&lt;/a&gt; like this one&lt;/li&gt;
&lt;li&gt;Giving a tech talk&lt;/li&gt;
&lt;li&gt;Writing a 
&lt;a href=&#34;https://davidbieber.com/posts&#34;&gt;blog post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Publishing a paper&lt;/li&gt;
&lt;li&gt;Uploading a video&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want to get infrequent updates about my progress, you can subscribe here:&lt;/p&gt;

&lt;link href=&#34;//cdn-images.mailchimp.com/embedcode/classic-10_7.css&#34; rel=&#34;stylesheet&#34; type=&#34;text/css&#34;&gt;
&lt;style type=&#34;text/css&#34;&gt;
  #mc_embed_signup{
    background:#fff;
    clear:left;
    font:14px Helvetica,Arial,sans-serif;
  }
&lt;/style&gt;
&lt;div id=&#34;mc_embed_signup&#34;&gt;
&lt;form action=&#34;https://gmail.us3.list-manage.com/subscribe/post?u=a55774562ae9fa9a1d879fa75&amp;amp;id=132f89def3&#34; method=&#34;post&#34; id=&#34;mc-embedded-subscribe-form&#34; name=&#34;mc-embedded-subscribe-form&#34; class=&#34;validate&#34; target=&#34;_blank&#34; novalidate&gt;
    &lt;div id=&#34;mc_embed_signup_scroll&#34;&gt;
  
&lt;div class=&#34;mc-field-group&#34;&gt;
  &lt;label for=&#34;mce-EMAIL&#34;&gt;Email Address&lt;/label&gt;
  &lt;input type=&#34;email&#34; value=&#34;&#34; name=&#34;EMAIL&#34; class=&#34;required email&#34; id=&#34;mce-EMAIL&#34;&gt;
&lt;/div&gt;
  &lt;div id=&#34;mce-responses&#34; class=&#34;clear&#34;&gt;
    &lt;div class=&#34;response&#34; id=&#34;mce-error-response&#34; style=&#34;display:none&#34;&gt;&lt;/div&gt;
    &lt;div class=&#34;response&#34; id=&#34;mce-success-response&#34; style=&#34;display:none&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;    
    &lt;div style=&#34;position: absolute; left: -5000px;&#34; aria-hidden=&#34;true&#34;&gt;&lt;input type=&#34;text&#34; name=&#34;b_a55774562ae9fa9a1d879fa75_132f89def3&#34; tabindex=&#34;-1&#34; value=&#34;&#34;&gt;&lt;/div&gt;
    &lt;div class=&#34;clear&#34;&gt;
      &lt;input type=&#34;submit&#34; value=&#34;Subscribe&#34; name=&#34;subscribe&#34; id=&#34;mc-embedded-subscribe&#34; class=&#34;button&#34;&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;script type=&#39;text/javascript&#39; src=&#39;//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js&#39;&gt;&lt;/script&gt;
&lt;script type=&#39;text/javascript&#39;&gt;(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]=&#39;EMAIL&#39;;ftypes[0]=&#39;email&#39;;fnames[1]=&#39;FNAME&#39;;ftypes[1]=&#39;text&#39;;fnames[2]=&#39;LNAME&#39;;ftypes[2]=&#39;text&#39;;fnames[3]=&#39;ADDRESS&#39;;ftypes[3]=&#39;address&#39;;fnames[4]=&#39;PHONE&#39;;ftypes[4]=&#39;phone&#39;;fnames[5]=&#39;BIRTHDAY&#39;;ftypes[5]=&#39;birthday&#39;;}(jQuery));var $mcj = jQuery.noConflict(true);&lt;/script&gt;

&lt;p&gt;You can expect fewer than one email per month, not 100 per year, so don&amp;rsquo;t worry about spam.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Writing for No Audience</title>
      <link>https://davidbieber.com/snippets/2019-12-30-writing-for-no-audience/</link>
      <pubDate>Mon, 30 Dec 2019 01:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2019-12-30-writing-for-no-audience/</guid>
      
        <message>Writing for no one is so much easier than writing for someone.</message>
      
      <description>&lt;p&gt;I started this 
&lt;a href=&#34;https://davidbieber.com/snippets&#34;&gt;&amp;ldquo;snippets&amp;rdquo;&lt;/a&gt; section of my website just a few days ago with the intention of being able to write without needing to put polish on a piece before publishing it.&lt;/p&gt;
&lt;p&gt;My thinking was that I would be able to put small notes there, and half-baked ideas, and not have to worry about diluting the quality of the content of my 
&lt;a href=&#34;https://davidbieber.com/posts&#34;&gt;main website&lt;/a&gt;. I could put high quality posts on the main site, and a whole range of both good and bad posts in the snippets section. This way, assuming I do a good job, readers could come to expect that any post on the main website would be high quality. Curious people looking for additional content could come here to the snippets section if they wanted to, but more often posts here would either (1) almost never get read, or (2) be linked to directly, e.g. if they were relevent in some other context.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been surprised and delighted by the effect that having this &amp;ldquo;No Audience&amp;rdquo; section of the website has had on my writing. Writing for no one is so much easier than writing for someone.&lt;/p&gt;
&lt;p&gt;On a few occasions (and it&amp;rsquo;s only been a few days since I started this section), I&amp;rsquo;ve started writing snippets intending for them to be brief thoughts meant for no one but myself. Then, after starting, it has felt natural to expand the post into something more substantial than I originally intended, e.g. answering questions that a hypothetical reader might have.&lt;/p&gt;
&lt;p&gt;On one 
&lt;a href=&#34;https://davidbieber.com/post/2019-12-29-track-your-life-in-a-spreadsheet&#34;&gt;occasion&lt;/a&gt; I even decided to bump the post up in importance after getting started, placing it in the main section of the website rather than relegating it to the mostly hidden snippets section.&lt;/p&gt;
&lt;p&gt;To anyone out there who does end up reading this, and there may very well be none of you: if you&amp;rsquo;re having trouble getting started with writing, write for no audience.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&#34;the-different-degrees-of-no-audience&#34;&gt;The Different Degrees of &amp;ldquo;No Audience&amp;rdquo;&lt;/h4&gt;
&lt;p&gt;I actually write for No Audience in two different contexts.&lt;/p&gt;
&lt;p&gt;(1) The 
&lt;a href=&#34;https://davidbieber.com/snippets&#34;&gt;snippets&lt;/a&gt; section of my website&lt;br&gt;
(2) Using 
&lt;a href=&#34;https://davidbieber.com/projects/shh-shell&#34;&gt;shh-shell&lt;/a&gt; at night&lt;/p&gt;
&lt;p&gt;The snippets section of my website is public, but with no built-in broadcasting. People can read it if they choose to, but I&amp;rsquo;m not putting it in people&amp;rsquo;s faces (by default; I will if it&amp;rsquo;s appropriate in context). Contrast this with the writing I do with the 
&lt;a href=&#34;https://davidbieber.com/projects/shh-shell&#34;&gt;shh-shell&lt;/a&gt;. This is more personal writing that I do half-asleep as I drift off at night, and so I don&amp;rsquo;t make it public; I expect almost no one will ever read it. This writing, I suppose is for No Audience to an even more extreme degree. I recommend both practices: public writing for no audience, and private writing for no audience.&lt;/p&gt;
&lt;h4 id=&#34;social-media-doesnt-cut-it&#34;&gt;Social Media Doesn&amp;rsquo;t Cut It&lt;/h4&gt;
&lt;p&gt;Now that I&amp;rsquo;ve discovered this practice and am quite fond of it, I think it could be a promising addition to social media.&lt;/p&gt;
&lt;p&gt;No social media platform, to my knowledge, has given people a place to write public posts with an option to publish but not share them. The absense of such a feature makes sense; social media platforms need you to share for them to succeed, so how would giving you a space to publish-but-not-share help them? The answer lies in the psychology of the many social-media lurkers. There is a significant market segment of people who perhaps consume, but do not post, on social media. An option to publish-but-not-broadcast might help to convert some of that segment into sharers.&lt;/p&gt;
&lt;p&gt;As a social media consumer, but infrequent producer, I can tell you I am hesitant even to Like something on Twitter, because I know Twitter often treats Likes like Retweets, and will put the content I hearted in front of my followers with my name attached, and that&amp;rsquo;s not something I want.&lt;/p&gt;
&lt;p&gt;If a feature for publishing-without-sharing were added to Facebook or Twitter, perhaps others would have an experience like mine over the last few days. Having the option to publish-but-not-share has significantly reduced the barrier to start writing for me. Then, once I&amp;rsquo;ve started writing, I&amp;rsquo;ve often changed my mind and decided I want to share what I&amp;rsquo;ve written after all.&lt;/p&gt;
&lt;p&gt;If other social-media lurkers are like me, a feature enabling this behavior could help &amp;ldquo;break the ice&amp;rdquo; so to speak, and could make social media platforms more relevant to them.&lt;/p&gt;
&lt;h4 id=&#34;next-steps&#34;&gt;Next Steps&lt;/h4&gt;
&lt;p&gt;I&amp;rsquo;m going to continue building this snippets section for myself, with the default behavior being no-broadcasting as I add snippets. For snippets I&amp;rsquo;m fond of, I may choose to broadcast (e.g. by posting about the post on social media). Contrast this with the 
&lt;a href=&#34;https://davidbieber.com/posts&#34;&gt;main posts section&lt;/a&gt; of my website; for new posts there, I will generally always broadcast the post, at least a little bit.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;d like to receive such broadcasts, e.g. when I write a post that I&amp;rsquo;m particularly keen on sharing, please consider subscribing:&lt;/p&gt;

&lt;link href=&#34;//cdn-images.mailchimp.com/embedcode/classic-10_7.css&#34; rel=&#34;stylesheet&#34; type=&#34;text/css&#34;&gt;
&lt;style type=&#34;text/css&#34;&gt;
  #mc_embed_signup{
    background:#fff;
    clear:left;
    font:14px Helvetica,Arial,sans-serif;
  }
&lt;/style&gt;
&lt;div id=&#34;mc_embed_signup&#34;&gt;
&lt;form action=&#34;https://gmail.us3.list-manage.com/subscribe/post?u=a55774562ae9fa9a1d879fa75&amp;amp;id=132f89def3&#34; method=&#34;post&#34; id=&#34;mc-embedded-subscribe-form&#34; name=&#34;mc-embedded-subscribe-form&#34; class=&#34;validate&#34; target=&#34;_blank&#34; novalidate&gt;
    &lt;div id=&#34;mc_embed_signup_scroll&#34;&gt;
  
&lt;div class=&#34;mc-field-group&#34;&gt;
  &lt;label for=&#34;mce-EMAIL&#34;&gt;Email Address&lt;/label&gt;
  &lt;input type=&#34;email&#34; value=&#34;&#34; name=&#34;EMAIL&#34; class=&#34;required email&#34; id=&#34;mce-EMAIL&#34;&gt;
&lt;/div&gt;
  &lt;div id=&#34;mce-responses&#34; class=&#34;clear&#34;&gt;
    &lt;div class=&#34;response&#34; id=&#34;mce-error-response&#34; style=&#34;display:none&#34;&gt;&lt;/div&gt;
    &lt;div class=&#34;response&#34; id=&#34;mce-success-response&#34; style=&#34;display:none&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;    
    &lt;div style=&#34;position: absolute; left: -5000px;&#34; aria-hidden=&#34;true&#34;&gt;&lt;input type=&#34;text&#34; name=&#34;b_a55774562ae9fa9a1d879fa75_132f89def3&#34; tabindex=&#34;-1&#34; value=&#34;&#34;&gt;&lt;/div&gt;
    &lt;div class=&#34;clear&#34;&gt;
      &lt;input type=&#34;submit&#34; value=&#34;Subscribe&#34; name=&#34;subscribe&#34; id=&#34;mc-embedded-subscribe&#34; class=&#34;button&#34;&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;script type=&#39;text/javascript&#39; src=&#39;//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js&#39;&gt;&lt;/script&gt;
&lt;script type=&#39;text/javascript&#39;&gt;(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]=&#39;EMAIL&#39;;ftypes[0]=&#39;email&#39;;fnames[1]=&#39;FNAME&#39;;ftypes[1]=&#39;text&#39;;fnames[2]=&#39;LNAME&#39;;ftypes[2]=&#39;text&#39;;fnames[3]=&#39;ADDRESS&#39;;ftypes[3]=&#39;address&#39;;fnames[4]=&#39;PHONE&#39;;ftypes[4]=&#39;phone&#39;;fnames[5]=&#39;BIRTHDAY&#39;;ftypes[5]=&#39;birthday&#39;;}(jQuery));var $mcj = jQuery.noConflict(true);&lt;/script&gt;

&lt;p&gt;Ironically, you are also welcome to follow the snippets section with 
&lt;a href=&#34;https://davidbieber.com/snippets/index.xml&#34;&gt;RSS&lt;/a&gt;. Don&amp;rsquo;t tell me if you do though, since I would like to continue to feel like I&amp;rsquo;m writing for No Audience. You can follow the posts section with 
&lt;a href=&#34;https://davidbieber.com/posts/index.xml&#34;&gt;RSS&lt;/a&gt; as well.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Planning to Analyze My Browsing History</title>
      <link>https://davidbieber.com/snippets/2019-12-30-analyzing-my-browser-history/</link>
      <pubDate>Mon, 30 Dec 2019 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2019-12-30-analyzing-my-browser-history/</guid>
      
        <message>I started a plan to analyze my browser history. This was my plan.</message>
      
      <description>&lt;p&gt;I&amp;rsquo;ve learned recently that programmatically accessing your browsing history is rather straightforward. Really exciting! This is rich data, from which I think I&amp;rsquo;ll be able to learn a lot and hopefully combat unwanted distractions.&lt;/p&gt;
&lt;p&gt;First let me describe what information is available, and how you can access it. Then, let&amp;rsquo;s discuss what you can do with this data. As I&amp;rsquo;ve written about previously 
&lt;a href=&#34;https://davidbieber.com/projects/bieber-bot/&#34;&gt;[1]&lt;/a&gt; 
&lt;a href=&#34;https://davidbieber.com/post/2019-12-29-track-your-life-in-a-spreadsheet/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;[2]&lt;/a&gt;, I already have a chat bot system in place, which will be able to take advantage of this data to e.g. help me stay focused.&lt;/p&gt;
&lt;h4 id=&#34;accessing-your-browser-history&#34;&gt;Accessing Your Browser History&lt;/h4&gt;
&lt;p&gt;Thank you to GitHub user 
&lt;a href=&#34;https://github.com/dropmeaword&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;dropmeaword&lt;/a&gt; for compiling 
&lt;a href=&#34;https://gist.github.com/dropmeaword/9372cbeb29e8390521c2&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;this gist&lt;/a&gt; explaining how to access your browser history via sqlite3. The gist covers Safari, Chrome, and Firefox. In this post, I&amp;rsquo;ll just focus on Chrome on OSX, since that&amp;rsquo;s my primary mode of browsing.&lt;/p&gt;
&lt;p&gt;My Chrome browsing history is located at &lt;code&gt;~/Library/Application Support/Google/Chrome/Default/History&lt;/code&gt;. Since I use multiple profiles in Chrome, each profile gets its own browsing history, e.g. located at &lt;code&gt;~/Library/Application Support/Google/Chrome/Profile 1/History&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Each browsing history is stored as a sqlite3 database. Before analyzing the data, I recommend making a copy of it (&lt;code&gt;cp ~/Library/Application\ Support/Google/Chrome/Default/History my-history&lt;/code&gt;); this way your history database (a) won&amp;rsquo;t be locked by Chrome while you&amp;rsquo;re trying to access it, and (b) won&amp;rsquo;t change while you&amp;rsquo;re looking at it, which could cause confusion and inconsistencies in your results.&lt;/p&gt;
&lt;p&gt;This means you can browse it interactively using the sqlite3 REPL by running &lt;code&gt;sqlite3 PATH_TO_DATABASE&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are also libraries available for accessing sqlite3 databases in just about every language. For Python, there&amp;rsquo;s the 
&lt;a href=&#34;https://docs.python.org/3/library/sqlite3.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;sqlite3&lt;/a&gt; library. Go has 
&lt;a href=&#34;https://godoc.org/github.com/mattn/go-sqlite3&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;go-sqlite3&lt;/a&gt;. JavaScript has 
&lt;a href=&#34;https://www.sqlitetutorial.net/sqlite-nodejs/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;this sqlite3 module&lt;/a&gt;. However you most like scripting, you&amp;rsquo;ll have a familiar way of accessing the data.&lt;/p&gt;
&lt;h4 id=&#34;the-available-data&#34;&gt;The Available Data&lt;/h4&gt;
&lt;p&gt;Running sqlite3 macro &lt;code&gt;.tables&lt;/code&gt;, we see the following tables are available.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;downloads&lt;/td&gt;
&lt;td&gt;meta&lt;/td&gt;
&lt;td&gt;urls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;downloads_slices&lt;/td&gt;
&lt;td&gt;segment_usage&lt;/td&gt;
&lt;td&gt;visit_source&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;downloads_url_chains&lt;/td&gt;
&lt;td&gt;segments&lt;/td&gt;
&lt;td&gt;visits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;keyword_search_terms&lt;/td&gt;
&lt;td&gt;typed_url_sync_metadata&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;We&amp;rsquo;ll be most interested in the &lt;code&gt;urls&lt;/code&gt; and &lt;code&gt;visits&lt;/code&gt; tables.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;urls&lt;/code&gt; table has these columns (found with &lt;code&gt;.schema urls&lt;/code&gt;):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Column&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;Integer Id&lt;/td&gt;
&lt;td&gt;The &lt;code&gt;id&lt;/code&gt; of the URL in the database.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;url&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;The URL of the website.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;title&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;The title of website.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;visit_count&lt;/td&gt;
&lt;td&gt;Integer&lt;/td&gt;
&lt;td&gt;The number of times you&amp;rsquo;ve visited the URL.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;typed_count&lt;/td&gt;
&lt;td&gt;Integer&lt;/td&gt;
&lt;td&gt;The number of times you&amp;rsquo;ve visited the URL by typing in the address (as opposed to by following a link.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;last_visit_time&lt;/td&gt;
&lt;td&gt;Integer (microseconds since the epoch)&lt;/td&gt;
&lt;td&gt;The time of the most recent to the URL.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hidden&lt;/td&gt;
&lt;td&gt;Boolean&lt;/td&gt;
&lt;td&gt;I&amp;rsquo;m not sure what this is about.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;And the &lt;code&gt;visits&lt;/code&gt; table has these columns (obtained via &lt;code&gt;.schema visits&lt;/code&gt;):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Column&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;Integer Id&lt;/td&gt;
&lt;td&gt;The &lt;code&gt;id&lt;/code&gt; of the visit in the database.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;url&lt;/td&gt;
&lt;td&gt;Integer Id&lt;/td&gt;
&lt;td&gt;The &lt;code&gt;id&lt;/code&gt; of the url in the &lt;code&gt;urls&lt;/code&gt; table.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;visit_time&lt;/td&gt;
&lt;td&gt;Integer (milliseconds since the epoch)&lt;/td&gt;
&lt;td&gt;The time of the visit.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;from_visit&lt;/td&gt;
&lt;td&gt;Integer Id&lt;/td&gt;
&lt;td&gt;The &lt;code&gt;id&lt;/code&gt; of the visit that lead you to this one.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;transition&lt;/td&gt;
&lt;td&gt;Bit vector&lt;/td&gt;
&lt;td&gt;Represents the 
&lt;a href=&#34;https://developer.chrome.com/extensions/history#transition_types&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;transition type&lt;/a&gt; (how you got to the URL)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;segment_id&lt;/td&gt;
&lt;td&gt;Integer Id&lt;/td&gt;
&lt;td&gt;The &lt;code&gt;id&lt;/code&gt; of the segment in the database. I&amp;rsquo;m not quite sure what a segment is, but there is a &lt;code&gt;segments&lt;/code&gt; table you can look at.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;visit_duration&lt;/td&gt;
&lt;td&gt;Integer (microseconds)&lt;/td&gt;
&lt;td&gt;The amount of time spent at the website, or 0 if not available.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;incremented_omnibox_typed_score&lt;/td&gt;
&lt;td&gt;Boolean&lt;/td&gt;
&lt;td&gt;I do not know what this is about.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;As you can see, we can access every visit to every website that we&amp;rsquo;ve made since the last time we cleared our browsing history. We can see what website we visited (&lt;code&gt;visits.url&lt;/code&gt;), when we visited it (&lt;code&gt;visits.visit_time&lt;/code&gt;), how many times we&amp;rsquo;ve visited it (&lt;code&gt;urls.visit_count&lt;/code&gt;), and how long each visit was for (&lt;code&gt;visits.visit_duration&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;We can even use &lt;code&gt;visits.from_visit&lt;/code&gt; to figure out what website linked us to each url, if that interests us.&lt;/p&gt;
&lt;h4 id=&#34;what-can-we-deduce&#34;&gt;What Can We Deduce?&lt;/h4&gt;
&lt;p&gt;We can (1) perform a historical analysis on the data, as well as (2) do real-time monitoring of the data.&lt;/p&gt;
&lt;p&gt;Here I brainstorm some of the historical trends we will be able to uncover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Most frequently visited websites&lt;/li&gt;
&lt;li&gt;Websites where we spend the majority of our time&lt;/li&gt;
&lt;li&gt;Websites that frequently lead to known-distractor websites (e.g. Reddit, Hacker News, Twitter, YouTube)&lt;/li&gt;
&lt;li&gt;We can do an analysis by time of day (or day of week), to figure out what sites occupy my time late at night vs during daylight hours.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are somewhat interesting, but what I&amp;rsquo;m particularly excited for is the ongoing analysis that 
&lt;a href=&#34;https://davidbieber.com/projects/bieber-bot&#34;&gt;Bieber Bot&lt;/a&gt; can provide by accessing the data.&lt;/p&gt;
&lt;p&gt;Here is a brainstorm of the more real-time actionable insights we might extract from this data.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bieber Bot could ping me if it looks like I&amp;rsquo;m spending too much time on a distraction website.&lt;/li&gt;
&lt;li&gt;He could try to detect if I went to a website with a particular purpose, but ended up getting distracted and not completing the purpose I set out to do.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, if I&amp;rsquo;m on a productive website and then switch to a distraction website for more than a few minutes, particularly during work hours, Bieber Bot might message asking if I got distracted. Think you could do that for me Bieber Bot?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I could signal that I want to view a website later by opening it and immediately closing it again.&lt;/li&gt;
&lt;li&gt;Perhaps we could detect if I&amp;rsquo;m researching a particular topic, and then Bieber Bot could try to help me with my research.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;related-idea&#34;&gt;Related Idea&lt;/h4&gt;
&lt;p&gt;In order to reduce distractions, I&amp;rsquo;d like to be able to switch my browsing mode from &amp;ldquo;clicking opens links&amp;rdquo; to &amp;ldquo;clicking saves a link for later&amp;rdquo;. When in this new mode, whenever I click a link it wouldn&amp;rsquo;t open that link; instead, it would save the link to a list of deferred links.
Then I would be able to view my &amp;ldquo;saved for later&amp;rdquo; links when I have time that I&amp;rsquo;ve explicitly set aside, rather than during the time that I would rather be doing something more productive.&lt;/p&gt;
&lt;h4 id=&#34;next-steps&#34;&gt;Next Steps&lt;/h4&gt;
&lt;p&gt;So far I&amp;rsquo;ve done a little bit of manual exploration of my browsing history data. I&amp;rsquo;ve set up a little Python script to be able to access the data programmatically.&lt;/p&gt;
&lt;p&gt;Next, I&amp;rsquo;ll do more manual analysis, and then I&amp;rsquo;ll see if I&amp;rsquo;m able to give Bieber Bot the real-time access to the data that I described above. I&amp;rsquo;m particularly excited to see if I can get the &amp;ldquo;looks like you&amp;rsquo;ve gotten distracted&amp;rdquo; messages set up with Bieber Bot. As a bonus, since Bieber Bot can message other people too, this system could help me leverage social accountability to stay on task.&lt;/p&gt;
&lt;p&gt;Want to see where this project leads? You can subscribe for infrequent email updates.&lt;/p&gt;

&lt;link href=&#34;//cdn-images.mailchimp.com/embedcode/classic-10_7.css&#34; rel=&#34;stylesheet&#34; type=&#34;text/css&#34;&gt;
&lt;style type=&#34;text/css&#34;&gt;
  #mc_embed_signup{
    background:#fff;
    clear:left;
    font:14px Helvetica,Arial,sans-serif;
  }
&lt;/style&gt;
&lt;div id=&#34;mc_embed_signup&#34;&gt;
&lt;form action=&#34;https://gmail.us3.list-manage.com/subscribe/post?u=a55774562ae9fa9a1d879fa75&amp;amp;id=132f89def3&#34; method=&#34;post&#34; id=&#34;mc-embedded-subscribe-form&#34; name=&#34;mc-embedded-subscribe-form&#34; class=&#34;validate&#34; target=&#34;_blank&#34; novalidate&gt;
    &lt;div id=&#34;mc_embed_signup_scroll&#34;&gt;
  
&lt;div class=&#34;mc-field-group&#34;&gt;
  &lt;label for=&#34;mce-EMAIL&#34;&gt;Email Address&lt;/label&gt;
  &lt;input type=&#34;email&#34; value=&#34;&#34; name=&#34;EMAIL&#34; class=&#34;required email&#34; id=&#34;mce-EMAIL&#34;&gt;
&lt;/div&gt;
  &lt;div id=&#34;mce-responses&#34; class=&#34;clear&#34;&gt;
    &lt;div class=&#34;response&#34; id=&#34;mce-error-response&#34; style=&#34;display:none&#34;&gt;&lt;/div&gt;
    &lt;div class=&#34;response&#34; id=&#34;mce-success-response&#34; style=&#34;display:none&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;    
    &lt;div style=&#34;position: absolute; left: -5000px;&#34; aria-hidden=&#34;true&#34;&gt;&lt;input type=&#34;text&#34; name=&#34;b_a55774562ae9fa9a1d879fa75_132f89def3&#34; tabindex=&#34;-1&#34; value=&#34;&#34;&gt;&lt;/div&gt;
    &lt;div class=&#34;clear&#34;&gt;
      &lt;input type=&#34;submit&#34; value=&#34;Subscribe&#34; name=&#34;subscribe&#34; id=&#34;mc-embedded-subscribe&#34; class=&#34;button&#34;&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;script type=&#39;text/javascript&#39; src=&#39;//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js&#39;&gt;&lt;/script&gt;
&lt;script type=&#39;text/javascript&#39;&gt;(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]=&#39;EMAIL&#39;;ftypes[0]=&#39;email&#39;;fnames[1]=&#39;FNAME&#39;;ftypes[1]=&#39;text&#39;;fnames[2]=&#39;LNAME&#39;;ftypes[2]=&#39;text&#39;;fnames[3]=&#39;ADDRESS&#39;;ftypes[3]=&#39;address&#39;;fnames[4]=&#39;PHONE&#39;;ftypes[4]=&#39;phone&#39;;fnames[5]=&#39;BIRTHDAY&#39;;ftypes[5]=&#39;birthday&#39;;}(jQuery));var $mcj = jQuery.noConflict(true);&lt;/script&gt;

</description>
    </item>
    
    <item>
      <title>Today I Learned the Word Feedingstuffs</title>
      <link>https://davidbieber.com/snippets/2019-12-29-feedingstuffs/</link>
      <pubDate>Sun, 29 Dec 2019 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2019-12-29-feedingstuffs/</guid>
      
        <message>That was when I learned the word &#39;feedingstuffs&#39;.</message>
      
      <description>&lt;p&gt;Today I learned the word 
&lt;a href=&#34;https://en.wiktionary.org/wiki/feedingstuff#English&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&amp;ldquo;feedingstuffs&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-md&#34;&gt;feedingstuff (countable and uncountable, plural feedingstuffs)

  Any foodstuff used to feed livestock.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&amp;rsquo;s not in every dictionary, and it&amp;rsquo;s not a valid Scrabble word.&lt;/p&gt;
&lt;p&gt;How did this word come up? I had heard previously that salmon is not naturally as pink as it is in supermarkets. I was wondering how this could be. Surely salmon aren&amp;rsquo;t being colored during the packaging process, right? That&amp;rsquo;s right, salmon are still that same color when they&amp;rsquo;re first cut open.&lt;/p&gt;
&lt;p&gt;The coloring, 
&lt;a href=&#34;https://ec.europa.eu/food/sites/food/files/safety/docs/animal-feed_additives_rules_scan-old_report_out81.pdf&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;I learned&lt;/a&gt;, is added to the salmon&amp;rsquo;s &lt;strong&gt;feedingstuffs&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;Yes, that&amp;rsquo;s an official European Commission report from 2002 recommending that the amount of allowable 
&lt;a href=&#34;https://en.wikipedia.org/wiki/Canthaxanthin&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Canthaxanthin&lt;/a&gt; (&lt;font color=&#34;salmon&#34;&gt;salmon&lt;/font&gt; coloring) in salmon feed be reevaluated, and possibly lowered.&lt;/p&gt;
&lt;p&gt;At the time, the maximum amount of Canthaxanthin allowable in salmon and trout feedingstuffs in the EU was 80 mg / kg of feedingstuff.&lt;/p&gt;
&lt;p&gt;Fast-forward to today, and only 
&lt;a href=&#34;https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX:32008R0775&amp;amp;qid=1577681296736&amp;amp;from=EN&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;10 mg / kg of Canthaxanthin is permitted&lt;/a&gt;. More interesting than this though, is that in the 2008 journal reporting this new, lower limit, they instead use the word &lt;strong&gt;foodstuffs&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Feedingstuffs, it would seem, are no more.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Learning to Communicate</title>
      <link>https://davidbieber.com/snippets/2019-12-26-learning-to-communicate/</link>
      <pubDate>Thu, 26 Dec 2019 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2019-12-26-learning-to-communicate/</guid>
      
        <message>My goal for 2020 was to learn to communicate better with the world. Still a goal for me.</message>
      
      <description>&lt;p&gt;My goal for 2020 is to learn to communicate better with the world. I work in a research group at Google, and our main job function is performing research in program synthesis. But research is only as valuable as how well it is communicated. So in 2020 I&amp;rsquo;d like to get better at communicating publicly.&lt;/p&gt;
&lt;p&gt;There are a few options for doing this. The first is writing blog posts. This may be too large an undertaking to do frequently. I&amp;rsquo;d really like something that&amp;rsquo;s lower barrier to do, and with a lower quality bar, so that I can do this more often. The natural alternative with these properties is academic Twitter. However, I want to avoid the addictive nature of Twitter. I also want to write more than 280 characters at a time, and I don&amp;rsquo;t want to put every little thing I write in front of people&amp;rsquo;s faces with equal importance. Twitter seems a good place for announcing a new paper or a Python Fire update, but not for sharing a musing like this one.&lt;/p&gt;
&lt;p&gt;So instead I think I&amp;rsquo;m going to start by silently posting my writings to my website, but in a 
&lt;a href=&#34;https://davidbieber.com/snippets&#34;&gt;separate section&lt;/a&gt; from the main blog. This way when there&amp;rsquo;s something with a little more polish that I think is explicitly worth reading, I can put it in the 
&lt;a href=&#34;https://davidbieber.com/posts&#34;&gt;main blog section&lt;/a&gt; and 
&lt;a href=&#34;https://twitter.com/Bieber&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;tweet&lt;/a&gt; about it, etc.&lt;/p&gt;
&lt;p&gt;If you want to receive updates for every small writing I put up here, you can use this 
&lt;a href=&#34;https://davidbieber.com/snippets/index.xml&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;RSS feed&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you want to receive updates only for major posts, such as new publications or major life updates, you can use this 
&lt;a href=&#34;https://davidbieber.com/posts/index.xml&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;RSS feed&lt;/a&gt; or you can subscribe here:&lt;/p&gt;

&lt;link href=&#34;//cdn-images.mailchimp.com/embedcode/classic-10_7.css&#34; rel=&#34;stylesheet&#34; type=&#34;text/css&#34;&gt;
&lt;style type=&#34;text/css&#34;&gt;
  #mc_embed_signup{
    background:#fff;
    clear:left;
    font:14px Helvetica,Arial,sans-serif;
  }
&lt;/style&gt;
&lt;div id=&#34;mc_embed_signup&#34;&gt;
&lt;form action=&#34;https://gmail.us3.list-manage.com/subscribe/post?u=a55774562ae9fa9a1d879fa75&amp;amp;id=132f89def3&#34; method=&#34;post&#34; id=&#34;mc-embedded-subscribe-form&#34; name=&#34;mc-embedded-subscribe-form&#34; class=&#34;validate&#34; target=&#34;_blank&#34; novalidate&gt;
    &lt;div id=&#34;mc_embed_signup_scroll&#34;&gt;
  
&lt;div class=&#34;mc-field-group&#34;&gt;
  &lt;label for=&#34;mce-EMAIL&#34;&gt;Email Address&lt;/label&gt;
  &lt;input type=&#34;email&#34; value=&#34;&#34; name=&#34;EMAIL&#34; class=&#34;required email&#34; id=&#34;mce-EMAIL&#34;&gt;
&lt;/div&gt;
  &lt;div id=&#34;mce-responses&#34; class=&#34;clear&#34;&gt;
    &lt;div class=&#34;response&#34; id=&#34;mce-error-response&#34; style=&#34;display:none&#34;&gt;&lt;/div&gt;
    &lt;div class=&#34;response&#34; id=&#34;mce-success-response&#34; style=&#34;display:none&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;    
    &lt;div style=&#34;position: absolute; left: -5000px;&#34; aria-hidden=&#34;true&#34;&gt;&lt;input type=&#34;text&#34; name=&#34;b_a55774562ae9fa9a1d879fa75_132f89def3&#34; tabindex=&#34;-1&#34; value=&#34;&#34;&gt;&lt;/div&gt;
    &lt;div class=&#34;clear&#34;&gt;
      &lt;input type=&#34;submit&#34; value=&#34;Subscribe&#34; name=&#34;subscribe&#34; id=&#34;mc-embedded-subscribe&#34; class=&#34;button&#34;&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;script type=&#39;text/javascript&#39; src=&#39;//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js&#39;&gt;&lt;/script&gt;
&lt;script type=&#39;text/javascript&#39;&gt;(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]=&#39;EMAIL&#39;;ftypes[0]=&#39;email&#39;;fnames[1]=&#39;FNAME&#39;;ftypes[1]=&#39;text&#39;;fnames[2]=&#39;LNAME&#39;;ftypes[2]=&#39;text&#39;;fnames[3]=&#39;ADDRESS&#39;;ftypes[3]=&#39;address&#39;;fnames[4]=&#39;PHONE&#39;;ftypes[4]=&#39;phone&#39;;fnames[5]=&#39;BIRTHDAY&#39;;ftypes[5]=&#39;birthday&#39;;}(jQuery));var $mcj = jQuery.noConflict(true);&lt;/script&gt;

&lt;p&gt;Happy early new year!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Snippets for davidbieber.com</title>
      <link>https://davidbieber.com/snippets/2019-12-25-introducing-snippets/</link>
      <pubDate>Wed, 25 Dec 2019 00:00:00 +0000</pubDate>
      
      <guid>https://davidbieber.com/snippets/2019-12-25-introducing-snippets/</guid>
      
        <message>Back in 2019 I introduced the &#39;snippets&#39; section to my website. This was my first snippet.</message>
      
      <description>&lt;p&gt;Today I&amp;rsquo;m introducing the &amp;ldquo;snippets&amp;rdquo; section of my website. The goal is to give myself a place to post content online that&amp;rsquo;s extremely easy to post to, but isn&amp;rsquo;t featured prominently anywhere on the site. This way I can post things without them needing polish or production value, but still link to them and share them as I see fit.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>