• Preview Note While Searching Org-Roam

    When searching for an org-roam note, the title isn’t always enough to tell if it’s what I was looking for. I want to preview the note without leaving the search interface (using helm).

    To do that, I adapted this helm source for org-roam.

    (defun helm-org-roam (&optional input candidates)
      (interactive)
      (require 'org-roam)
      (helm
       :input input
       :sources (list
                 (helm-build-sync-source "Find note: "
                   :must-match nil
                   :fuzzy-match t
                   :candidates (or candidates (org-roam-node-read--completions))
                   :persistent-action (lambda (x)
                                        (--> x
                                             (view-file (org-roam-node-file it))))
                   :action
                   '(("Find File" . (lambda (x)
                                      (--> x
                                           (org-roam-node-visit it t))))
                     ("Preview" . (lambda (x)
                                    (--> x
                                         (view-file (org-roam-node-file it)))))
                     ("Insert link" . (lambda (x)
                                        (--> x
                                             (insert
                                              (format
                                               "[[id:%s][%s]]"
                                               (org-roam-node-id it)
                                               (org-roam-node-title it))))))
                     ("Follow backlinks" . (lambda (x)
                                             (let ((candidates
                                                    (--> x
                                                         org-roam-backlinks-get
                                                         (--map
                                                          (org-roam-node-title
                                                           (org-roam-backlink-source-node it))
                                                          it))))
                                               (helm-org-roam nil (or candidates (list x))))))))
                 (helm-build-dummy-source
                     "Create note"
                   :action '(("Capture note" . (lambda (candidate)
                                                 (org-roam-capture-
                                                  :node (org-roam-node-create :title candidate)
                                                  :props '(:finalize find-file)))))))))
    
      (global-set-key (kbd "C-c n f") 'helm-org-roam)
    

    Now when I have a list of search results I can preview the file using the C-j without leaving the search session.


    Published

  • How to Work Asynchronously

    One of the greatest advantages that remote-first companies have is that work happens asynchronously. I lead to a culture of writing things down. It allows teams to be flexible between working styles and time-zones (up to a point). It creates a more equitable environment regardless of physical location.

    Despite the advantages, setting up an asynchronous working process can be tricky. Here’s a few simple playbooks to follow.

    This is a work in progress!

    Running a project

    If you’re running a project and the team works asynchronously, here’s what you need to do.

    1. Write a project brief Take the first stab at answering a key question. Talk to people as needed to get the information you need and be sure you have an initial answer.
    2. Share a link to the document in public channels, tag specific people for feedback, and ask that all feedback is added as comments to the document Comments in a document are naturally asynchronous. They act as an inbox for feedback and there should be no expectation that they will be answered immediately. If you get other feedback in Slack for example, direct people to add it to the doc (conversations get lost, are more synchronous, and chat apps are not a good place to find things later).
    3. Resolve the comments, have ad-hoc discussions as needed to gather more input Be editorial. Resolve what is necessary and decide what you won’t address. Anyone should be able to give feedback, but that doesn’t mean everything needs to be resolved.
    4. If you are unable to make all of the decisions, hold a meeting to resolve them and kick off the project

    Saving meetings for the end of the process reserved for making decisions (if needed) leads to a more inclusive environment. The interface for providing feedback is clear and avoids the tyranny of structurelessness.

    Even better, you now have a document you can reference as the project progresses and point people to if they have questions. (Documents are better than people at answering questions).


    Published

  • Frequency Range of Hearing Is Probably the Same in the Universe

    Organisms evolving independently on different planets will probably end up with the ability to hear things at the same frequency range as humans. That’s because the sound a predator makes as it approaches would be in the same spectrum regardless of atmosphere. Organisms that could react to these frequencies would have an advantage and survive.

    I read about this idea in Project Hail Mary.

    See also:

    • Similarity between organisms in different planets could also be evidence for panspermia but even without starting from a common “seed”, natural selection seems like it would yield similar traits
    • Then again, maybe life is another aspect of the anthropic principle

    Published

  • Levels of Accountability

    Accountability is a distinguishing feature of progressing into leadership roles. As a general rule, moving “up” means more accountability. Being a high performing contributor means being accountable for yourself. Being a leader means being accountable for others. Being an executive means being accountable for what you can not control (e.g. the market). There are many counter examples where leaders are not held accountable or getting promoted doesn’t increase the level of accountability, but acting as a principal is still the best strategy.

    The opposite of this (and something to screen for when working with others) is learned helplessness—there is a belief in one’s agency needed to take accountability. That’s why founders, who are accountable for things outside of their control, seem to require a controlled self-deception or they wouldn’t start anything. That’s why default optimism is rational.


    Published

  • Never Share Your Desktop When Screen Sharing

    When screen sharing, never share your whole screen. There is too much information that will be viewable on your desktop and infinite ways to accidentally leak private stuff. I can’t count the number of times someone screen sharing over Zoom accidentally had their personal chat messages showing or a browser tab with something embarrassing.

    A few simple rules for safer screen sharing:

    • Always select the option to share a specific window, never share your whole desktop (your desktop will show all of your open applications, new notifications, thumbnails of pictures, document names, and so on)
    • If you are sharing your browser, open a new window (not a new tab!) and share only the new window (your tabs contain a lot of information that is unnecessary to expose)
    • If you need to open a new link, open a new window and navigate to the link then copy the link to your sharing window (Google Chrome will autocomplete search history which may leak sensitive information)

    See also:


    Published

  • Principles for Living a Rich Digital Life

    I’ve been thinking more about how to live a rich digital life and what that means in a world of abundance. The following is a work-in-progress list of principles that are starting to form. (Epistemic status: low).

    Stay connected: The digital age has made it easier than ever to stay connected with others, whether through social media, messaging apps, or other online platforms. Make the most of this abundance of connectivity by reaching out to others and building a network of supportive relationships.

    • Healthy social media?

    Learn continuously: The digital world is constantly changing, and it’s important to keep up with the latest developments and trends stay relevant and competitive. Look for opportunities to learn new skills and technologies, and be open to trying new things.

    Mold it to you: code and connect things so that your stack does what you want it to do. Don’t settle for the out-of-the-box experience. This means having the skills to do so by learning to code and keeping up with technology.

    • Being efficient with keyboard shortcuts
    • Customizing your keyboard to be faster
    • Writing elisp to extend emacs

    Stay organized: With so much information and content available online, it’s easy to get overwhelmed. Stay organized and focused by setting goals, prioritizing tasks, and using tools like calendars and to-do lists to stay on track.

    Protect your privacy: The abundance of personal data available online can also make it more important to protect your privacy. Be mindful of the information you share online, and consider using privacy tools like virtual private networks (VPNs) and password managers to keep your data secure.

    • Avoid ads

    Take breaks: It’s easy to get caught up in the constant flow of information and distractions online, but it’s important to take breaks and disconnect from time to time. Make sure to set aside time for offline activities and relaxation, and prioritize self-care to maintain a healthy balance.

    Make money from the internet: The internet economy is booming and making money from anywhere is a reality with remote work.

    See also:


    Published

  • Roman Concrete Was Self-Healing

    Roman concrete used thousands of years ago is significantly more durable than modern concrete. One of the key differences is self-healing properties—when Roman concrete cracks, it reacts with water which quickly fills in the crack with calcium carbonate.

    A recent study looked into how Roman concrete was made and tested these properties. They found that hot mixing must have been used to create quicklime instead of slaked lime. This creates more surface area within the mortar area and is the source of reactive calcium which fills in cracks over time.

    See also:


    Published

  • Containing Multitudes on the Internet

    The internet is a place of digital abundance with zero friction to publishing. Building an audience is increasingly important for one’s long-term prospects. This leads to deep niches filling the internet.

    This is mostly a good thing—interesting content for more people and diversity of things—but also makes it harder to contain multitudes on today’s internet.

    There are penalties built into the way we publish and consume content. For example, you can find your 1000 true fans in some obscure automatic watch community but they probably don’t want to hear about you learning to program Rust. Platforms like Facebook, Twitter, TicToc, and to a lesser extent, forums and chat groups, aggregate audiences that only want to hear from a limited part of you.

    As a founder, tinkerer, programmer, and writer, I find myself in this generalist dilemma all the time. How do you contain multitudes on the internet?

    Somewhat inspired by this post, The internet wants to be fragmented by Noahpinion because I don’t want to be fragmented.


    Published

  • Tools for Thought Are Necessarily Monolithic

    I read Unbundling Tools for Thought and I find myself agreeing and disagreeing. They are correct that people over invest in tools for networked thought and can get stuck in an unproductive cycle of rebuilding the system over and over again. They are incorrect that the solution is to unbundle into multiple tools and interop between them—point solutions are good at what they do but don’t provide as much building material needed to make it a home.

    A good tool for thought is necessarily monolithic. It must cover the surface area of your life in order to be useful (for me that’s personal and professional work). It must be flexible to accommodate the idiosyncrasies of how you think. The combination of coverage and fit means that an effective tool for thought needs to do a lot of things for a lot of different kinds of people.


    Published

  • Delegation Not Abdication

    A common mistake for early managers is to delegate work ineffectively. They try to do what they think their direct reports would want—assign a task and be completely hands-off. It’s the right instinct but seldom yields the right results. Problems occur when mistaking abdication for delegation.

    Delegation is ensuring the person has what they need to accomplish the task and setting expectations about what needs to be done. If the person doesn’t have the ability or resources to do the work then it won’t get done and you’ve failed to delegate. If the person doesn’t know what needs to be done or you don’t check to make sure it is done well, you’ve failed to delegate.

    As a manager, you are responsible for results. If your reports fail, you’ve failed. You need to successfully enable people to do work, check it, and make sure what comes out is of high quality.

    Delegation is an active process. Abdication is a passive process.

    See also:


    Published

  • Squash Migrations Using Alembic and Postgres

    Over time, a Python project accumulates many migrations using alembic. This can slow down tests (you need to run all migrations every time you create a test DB) and it’s very unlikely you will ever rollback past a certain point in time.

    There’s no straightforward way of squashing migrations into one that I could find in alembic. I found that I couldn’t use the trick of running alembic revision --autogenerate because we don’t use ORM models to represent the entire schema. Instead, the combination of pg_dump and alembic stamp gives a similar result that allows us to squash everything into one migration.

    Get the schema of DB as SQL

    First we need to get the schema as a set of SQL statements using pg_dump. This needs to be done on the database that matches the actual schema in production (or maybe run it on production). Unless you are meticulous about using DB migrations, there might be some drift between the schema in your local database and what’s actually in production.

    pg_dump -s --user {your app user} {name of db} > squash.sql
    

    Verify and clean up

    For my purposes, I removed the auto-generated SET statements, removed the auto-generated ownership statements (otherwise test DBs run using a different user would fail), and tried loading it in a clean DB to see if the tables match.

    Create a migration and wrap the generated SQL statements

    Generate a new migration that runs the generated pg_dump SQL.

    The migration should look something like this:

    # revision identifiers, used by Alembic.
    revision = "123456789"
    down_revision = None
    branch_labels = None
    depends_on = None
    
    
    def upgrade():
        with open(f"{PROJECT_ROOT_DIR}/alembic/versions/squash.sql", "r") as f:
            for stmt in f.read().split(";\n"):
                if not stmt:
                    continue
                op.execute(stmt)
    

    Delete all previous migrations

    You can now delete all of the old migrations and try out the new squashed migration to see that it takes a clean DB and produces the expected schema using alembic upgrade head.

    Note: check very closely that the squashed migration actually gets your DB into the shape you want. For me, I needed to add some extra calls to pre-populate some data that were snuck in from previous migrations using handwritten INSERT statements.

    Skip the migration in production

    [WIP I haven’t verified this yet!] You don’t want to run the squashed migration in production. To skip it, run alembic stamp head which will mark the latest migration as the lastest version. New migrations can be applied on top safely using the usual alembic revision commands.


    Published

  • How to Ramp Up a Software Engineer

    To get a new software engineer up to speed quickly, several things must already be in place. An assigned buddy who can be the first point of contact for questions or issues that arise. A manager with a written ramp up plan for the new employee with clear guidance on performance expectations. A self-serve development environment with clear documentation for getting your code base running locally.

    An assigned buddy helps to make the first few weeks of getting started easier. They will set up time with the new hire on their first day to point them in the right direction. They can help troubleshoot issues the new hire may encounter. They will assign small tasks to get exposure to the code base. They’re also a friendly face that they don’t have to feel bad about asking questions.

    Giving explicit permission that it’s is okay to ask questions and take the buddy’s time is very important. When you are new, defaulting to “I don’t want to bother people” is common, but is a detriment to getting up to speed. Remote teams in particular, need to be more deliberate about everything.

    The manager of the new engineer is responsible for making sure the new hire understands what is expected of them. The simplest way to do that is to share a 30/60/90 plan and review it at the first one-on-one meeting. The first 30 days should be about solving small tasks that have already been flagged from the backlog which are self-contained and less than a day of work for a fully ramped engineer. At 60 days, they should start working on a medium size project that is has already been scoped out (i.e. there is a reasonable level of technical details worked out so that such that it looks like a list of small tasks). For career level engineers, at 90 days, it’s time to lead a project that they scope out and deliver with one or two other engineers.

    The plan gives the manager and new hire something to check in on regularly to make sure expectations are being met. If expectations are not being met according the timeline, share feedback and make an adjustment. If the new hire is repeatedly not meeting expectations it’s time to part ways.

    A common mistake is to move on to working on projects too early. Shipping small things (1 small thing per day) builds familiarity with the code base and problem domain. Getting things done is the foundation of just about everything and it is much more difficult to assess how it’s going when they start working on larger, more complicated projects.

    It’s likely that your systems and working environment will cause an otherwise successful engineer to fail. Parting ways early if it isn’t working out is best for both parties—you need engineers to hit the ground running and they deserve to work at a place that maximizes their ability to do great work.

    A self-serve development environment should be in place so that a new engineer can ship to production on the first day. For example, running a single command to get a fully working local environment (as much as I don’t like docker, it’s still the best for this) and having an easy way to deploy to production. Without this, even the most experienced engineers will spend days if not weeks, struggling to get the right toolchain and packages installed.

    See also:


    Published

  • Illusion of Explanatory Depth

    People feel they understand things better than they actually do. This leads to biases and poor decision-making because of overconfidence in their knowledge.

    A simple way to combat the illusion of explanatory depth is to ask yourself to explain something you just encountered. As you start to analyze it in more detail you can see your ability to explain phenomena diminish. On the contrary, explaining in layers makes the illusion worse when you successfully explain the higher level layer of abstraction and then proceed to lower levels (e.g. explaining how a computer works by starting with the layer of how the peripherals fit together like a keyboard, mouse, and display).

    According to this study, the illusion of explanatory depth might be a coping mechanism for reducing cognitive load. It might be beneficial for example to have a sparse representation of causal relations that are good enough for everyday purposes.

    See also:


    Published