<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Björn Andersson</title>
    <description>The latest articles on DEV Community by Björn Andersson (@gaqzi).</description>
    <link>https://dev.to/gaqzi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F11949%2Fffa28b2c-68c5-4f7f-a58d-fc9cf40608a8.jpeg</url>
      <title>DEV Community: Björn Andersson</title>
      <link>https://dev.to/gaqzi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gaqzi"/>
    <language>en</language>
    <item>
      <title>Your name is still on it — learning to ride the AI motorcycle without crashing</title>
      <dc:creator>Björn Andersson</dc:creator>
      <pubDate>Thu, 24 Jul 2025 15:00:00 +0000</pubDate>
      <link>https://dev.to/gaqzi/your-name-is-still-on-it-learning-to-ride-the-ai-motorcycle-without-crashing-5ajj</link>
      <guid>https://dev.to/gaqzi/your-name-is-still-on-it-learning-to-ride-the-ai-motorcycle-without-crashing-5ajj</guid>
      <description>&lt;p&gt;A colleague recently said something that’s been rattling around in my head: “AI gives you speed, but it doesn’t give you direction.” And the more I use these tools, the more I think that undersells the danger.&lt;/p&gt;

&lt;p&gt;I have been wondering how to think about AIs (or &lt;a href="https://newsletter.pragmaticengineer.com/p/tdd-ai-agents-and-coding-with-kent" rel="noopener noreferrer"&gt;genies&lt;/a&gt;) and how &lt;a href="https://medium.learningbyshipping.com/bicycle-121262546097" rel="noopener noreferrer"&gt;computers are like bicycles for the mind&lt;/a&gt;, as Steve Jobs put it, and I think these tools take it further. They are more like motorcycles for the mind. They go &lt;em&gt;really&lt;/em&gt; fast, and you better not treat them like a bike, because you need to know what you’re doing. How to handle that thing. You need to make sure you don’t try to go too fast too soon, or for too long, because you’ll get speed blind and… things will happen.&lt;/p&gt;

&lt;p&gt;I’m pretty sure motorcycle insurance costs way more when you’re in your 20s than in your 40s or 50s. There’s a reason for that. People who are older generally know how to ride the thing, and they’re not as wild when doing it.&lt;/p&gt;

&lt;p&gt;But I think when it comes to using AI we’re all kind of in our 20s because we’re figuring it out.&lt;/p&gt;

&lt;h2&gt;
  
  
  It’s my name on whatever goes out #
&lt;/h2&gt;

&lt;p&gt;I was at a wedding recently, talking to this lawyer, 50s, 60s maybe, working at a multinational. He’s been playing around with AI and feels it’s giving him an enormous productivity boost for writing and doing research for him.&lt;/p&gt;

&lt;p&gt;As we were talking about how he was using it he said something that stopped me cold: &lt;em&gt;“It’s my name on whatever goes out.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;He’s already caught the AI making things up. He has to check every line, every reference. He explicitly asks it to give him the references so he can look them up himself. And if I understood correctly, this isn’t significantly different from when juniors do the work for him. Because it was still his name on it. He needs to validate it. Whatever he puts his name on and sends out has to be right.&lt;/p&gt;

&lt;p&gt;And that’s when something clicked for me. &lt;a href="https://sanitarium.se/blog/2025/07/12/which-hat-are-you-wearing/" rel="noopener noreferrer"&gt;Remember how I was talking about the different hats we wear?&lt;/a&gt; Well, here’s the thing: you &lt;em&gt;can&lt;/em&gt; outsource wearing the hat. You &lt;em&gt;can&lt;/em&gt; have the genie do the work. But it’s still your name on it. No one else cares if you outsourced it, they only see your name on it. You can’t blame the genie for a shit job. It was your name.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we think we’re automating #
&lt;/h2&gt;

&lt;p&gt;I keep hearing engineers say, “&lt;em&gt;oh, I don’t have to do this boring thing anymore!&lt;/em&gt;”&lt;/p&gt;

&lt;p&gt;Meeting notes are a perfect example. I have access to Google Gemini at work, and people just let Gemini take meeting notes and send them out without reading them. Really. “&lt;em&gt;Huh?&lt;/em&gt;” I hear some of you say now, that’s what it’s great for, the notes are &lt;a href="https://sre.google/sre-book/eliminating-toil/" rel="noopener noreferrer"&gt;just toil&lt;/a&gt;. Well, no, what are meeting notes actually for? They’re about making sure we’re on the same page, that we have the same agreements and understanding. If you let the machine mindlessly capture words and don’t check that it actually documented the meaning behind what we said and understood, you’re failing at the actual job of &lt;a href="https://sanitarium.se/blog/2025/05/03/effective-meetings/" rel="noopener noreferrer"&gt;running that meeting.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This reminds me of &lt;a href="https://fs.blog/chestertons-fence/" rel="noopener noreferrer"&gt;Chesterton’s Fence&lt;/a&gt;, that principle about not removing a fence until you understand why it was put there. Before you automate away some “boring, pointless thing,” maybe ask yourself: why is it that I’m doing this in the first place? Because if you don’t understand why it’s done, how do you know the automation did it well?&lt;/p&gt;

&lt;p&gt;And I wonder if what’s really happening is that we’re not automating the work, we’re automating away our attention to the work. We’re not automating the output. We’re automating away our understanding of what that output should be. And here’s what we lose: &lt;a href="https://www.benkuhn.net/impact/" rel="noopener noreferrer"&gt;experienced people are the ones who spot strange patterns (or have taste)&lt;/a&gt; precisely because they’ve stayed engaged with the work over time. You can’t develop that instinct if you’re not looking.&lt;/p&gt;

&lt;h2&gt;
  
  
  The work worth doing #
&lt;/h2&gt;

&lt;p&gt;Which brings me to &lt;a href="https://tidyfirst.substack.com/p/90-of-my-skills-are-now-worth-0" rel="noopener noreferrer"&gt;something eyebrow raising&lt;/a&gt; that Kent Beck said: with AI, 90% of his skills became worthless, but the leverage of the remaining 10% is now worth 1000x. The question is: which 10%? This is the “&lt;em&gt;knowing where to put the X&lt;/em&gt;” skill, &lt;a href="https://sanitarium.se/blog/2025/07/12/which-hat-are-you-wearing/#the-9999-skill" rel="noopener noreferrer"&gt;that judgment call and experience&lt;/a&gt; you bring: that’s what makes the genie do what’s needed.&lt;/p&gt;

&lt;p&gt;When you let the genie write code for you and it introduces bugs that you would have caught if you’d actually read the code… you’re not doing your job as a product engineer. Yeah, you’re slinging more code and doing it faster. But it’s not about the code, it’s about delivering the solutions we need when we need them.&lt;/p&gt;

&lt;p&gt;There’s a difference between &lt;em&gt;delegating execution&lt;/em&gt; and &lt;em&gt;delegating responsibility&lt;/em&gt;. You &lt;em&gt;can&lt;/em&gt; have the genie execute tasks, but you &lt;em&gt;can’t&lt;/em&gt; delegate the responsibility for the outcome. That’s still yours. &lt;a href="https://sanitarium.se/blog/2025/07/12/which-hat-are-you-wearing/" rel="noopener noreferrer"&gt;The hat&lt;/a&gt; is still on your head, even if AI is helping you get things done faster while wearing it.&lt;/p&gt;

&lt;p&gt;And here’s the thing: there’s pride in doing the work well, even the boring bits. Sometimes we might not enjoy the work, but learning to enjoy doing it well will make most things worthwhile. Because there’s value in knowing how to do it well, in understanding why it matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding your balance #
&lt;/h2&gt;

&lt;p&gt;The question isn’t “can the genie do this task?” It’s “when it does this task and puts my name on it, am I comfortable with what might happen if it gets it really, really wrong?”&lt;/p&gt;

&lt;p&gt;In my experience, the engineers who are using AI most effectively are the ones who treat it like that lawyer treats it: as a powerful tool that still requires their full professional judgment. They understand they’re being paid for the judgment part of the work, not just the execution part. The genie can help with execution, it can draw lots of Xs quickly. But knowing where to draw them? That’s all you.&lt;/p&gt;

&lt;p&gt;Right now, these systems can’t truly understand context the way a senior does. They can’t make actual judgment calls, they’re pattern matching (even if, admittedly, &lt;a href="https://en.wikipedia.org/wiki/Clarke%27s_three_laws" rel="noopener noreferrer"&gt;slightly magical&lt;/a&gt; in how they do it). They give us speed, not judgment or direction. Output, not understanding.&lt;/p&gt;

&lt;p&gt;I’m still working out what learning looks like when AI can show you all the moves. My cooking has genuinely leveled up with an AI coach: I’m making dishes I never could before, and understanding why certain techniques work. But I know this is like training wheels. I couldn’t fully do this alone yet, and that’s the thing: I’m not mistaking this &lt;em&gt;speed&lt;/em&gt; for actual &lt;em&gt;skill&lt;/em&gt;, not confusing making &lt;em&gt;progress&lt;/em&gt; with real &lt;em&gt;proficiency&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So here I am, learning to ride this thing safely, trying to get out of my AI twenties you might say, before I take it on the highway.&lt;/p&gt;

&lt;p&gt;Because whether you’re wearing your engineering hat, your architect hat, or your team lead hat, your name is still on it. And I’d like to make sure I am not only wearing the helmet but also know how to ride this motorcycle before I really open up the throttle.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>genie</category>
      <category>roles</category>
      <category>leadership</category>
    </item>
    <item>
      <title>Which hat are you wearing? ...you wouldn't wear a beanie to the beach</title>
      <dc:creator>Björn Andersson</dc:creator>
      <pubDate>Sat, 12 Jul 2025 07:06:00 +0000</pubDate>
      <link>https://dev.to/gaqzi/which-hat-are-you-wearing-you-wouldnt-wear-a-beanie-to-the-beach-fce</link>
      <guid>https://dev.to/gaqzi/which-hat-are-you-wearing-you-wouldnt-wear-a-beanie-to-the-beach-fce</guid>
      <description>&lt;p&gt;I was in an incident review recently where one of the problems was a human going too fast. This process is very manual, repetitive, and boring, and it rarely fails, so we skip some steps. That mostly works (see &lt;a href="https://safetydifferently.com/why-do-things-go-right/" rel="noopener noreferrer"&gt;Why Do Things Go right?&lt;/a&gt;), except when it doesn’t. Ripe for occasional issues and likely in need of automation.&lt;/p&gt;

&lt;p&gt;I believe we often skip steps because we don’t know &lt;em&gt;why&lt;/em&gt; we do them. It’s not tedious for tediousness sake, it’s &lt;a href="https://fs.blog/chestertons-fence/" rel="noopener noreferrer"&gt;often there because it’s important&lt;/a&gt;. And until we have the automation, or maybe we’ve intentionally chosen not to automate it, we need to find some way of helping the human ’live the situation.'&lt;/p&gt;

&lt;p&gt;Which reminded me of this Terry Pratchett quote: “Every trade, every craft had its hat. That’s why kings had hats. Take the crown off a king and all you had was someone good at having a weak chin and waving to people. Hats had power. Hats were important.”&lt;/p&gt;

&lt;p&gt;And there’s something to this, right? Like in my own role as a principal engineer, I am definitely &lt;em&gt;seen&lt;/em&gt; as my role more often than I am the person beneath it. When people see me in a meeting, they see the title first. Hopefully I provide valuable insights and useful things. But even if I provide absolute garbage input, there’s a significant chance people will listen, and maybe even not push back, because of the hat.&lt;/p&gt;

&lt;p&gt;But, I have been wondering: what is your role and what is your ownership? What is it that you individually provide to whatever work you’re doing? And is it always the same hat?&lt;/p&gt;

&lt;h2&gt;
  
  
  The hat you don’t know you’re wearing #
&lt;/h2&gt;

&lt;p&gt;I think your hat changes depending on the role you’re fulfilling at the moment. When you’re working as a software engineer, you wear an engineering hat where you think about the feasibility of what you’re building, like, can I maintain this thing long term, how far will it scale, and how testable is this design?&lt;/p&gt;

&lt;p&gt;But if you’re working as a product engineer, you’re probably first thinking about how do I get this damn thing out the door, so you can see if it works or not. It’s about trying things, slapping it together, flinging it against the wall with the smallest responsible amount of tests (so you know you don’t break existing things when you iterate), and see what sticks.&lt;/p&gt;

&lt;p&gt;I’ve noticed, though, that we often forget to switch hats when we need to.&lt;/p&gt;

&lt;p&gt;Take deploying to production. When we’re about to take something live, we should be wearing a different hat. We need to embody the spirit of production itself, become its guardian of stability (yeah, yeah, too many roleplaying games). Some orgs have a “release manager” as a dedicated role, but even if it’s not a dedicated role, the need is always there. Taking things live is one of the most dangerous things we do: because most incidents happen when we change something. Whether it’s config, a flag, or code.&lt;/p&gt;

&lt;p&gt;The product engineer hat and the production guardian hat often feel very similar, and that’s exactly the problem. Just because a hat &lt;em&gt;is similar&lt;/em&gt; doesn’t mean &lt;em&gt;it’s the same.&lt;/em&gt; The product engineer wants the experiment live yesterday. The production guardian knows we can only ship today, and wants to make sure we still have a tomorrow. It’s this impossible tension, one person wanting to have already finished something we haven’t even started, the other pumping the brakes to make sure we don’t break what’s already working. And that often leads to “safety theater,” where we do it a little bit slower, say 30m to get everywhere instead of one quick change, to catch disasters but not slow burn issues. Obviously this tension changes, to use &lt;a href="https://medium.com/@kentbeck_7670/the-product-development-triathlon-6464e2763c46" rel="noopener noreferrer"&gt;Kent Beck’s 3X model&lt;/a&gt;, depending on whether you’re in eXplore, eXpand, or eXtract mode. We’re mostly in eXtract, so breaking things affects a lot of customers and the production guardian hat needs to be especially strong.&lt;/p&gt;

&lt;p&gt;For example, in another incident, someone didn’t manually check dashboards after deploying, which was part of the process, because they trusted the automated alerts. The alert came in after 10 minutes when it had enough data to be sure it wasn’t temporary. But a human who was actually monitoring, really living that production guardian role, would’ve realized something was wrong within a minute or two. The manual step was there because the team knew their automated alerts weren’t good enough to handle all issues around deployments.&lt;/p&gt;

&lt;p&gt;Where I work today, we have some 250 backend components. We can test all we want, black box integration tests, contract tests, end-to-end tests, manual QA, all of it. We’re still going to miss and get stuff wrong sometimes.&lt;/p&gt;

&lt;p&gt;The point and our challenge in mindset is: when we’re taking things into production, we’re not wearing the hat of the product engineer anymore. We’re taking on the role of production’s guardian, and we’re shepherding changes safely into production.&lt;/p&gt;

&lt;h2&gt;
  
  
  It’s like Vim modes, but for work #
&lt;/h2&gt;

&lt;p&gt;Say whatever you want about Vim, but one really nice thing is that it’s modal. The idea that I’m now doing this thing (inserting or editing text), and now I’m doing this other thing (normal or moving and transforming), and you behave differently in those modes.&lt;/p&gt;

&lt;p&gt;I see this in my own work all the time. I regularly review my own PRs because even though I went through everything when writing my commit message, I invariably look at it differently when I’m on GitHub in the interface I use for reviews. I switch much better into reviewer mode when I’m leaving comments there. It’s common that I review and leave myself comments for what to fix, discover I need a comment, or elaborate a little bit further on something the reviewer might not be familiar with.&lt;/p&gt;

&lt;p&gt;It’s like TDD in a way. When you’re red, you rush towards green by just getting it to work in the simplest way you humanly can. Then, when it’s green, when you got it working, you refactor it. Different modes, different goals.&lt;/p&gt;

&lt;p&gt;We need to be more intentional about which hat we’re wearing at the moment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Becoming the character #
&lt;/h2&gt;

&lt;p&gt;I saw this story about Christian Bale recently (and look, I can’t find the original source, so this might be one of those stories that’s too good to fact-check, but it perfectly captures what I’m talking about). He’s a famous &lt;a href="https://en.wikipedia.org/wiki/Method_acting" rel="noopener noreferrer"&gt;method actor&lt;/a&gt;, someone who becomes their characters completely. Apparently, when he wasn’t getting much work, he dreaded having to read through his insurance contract and have that conversation because it was boring.&lt;/p&gt;

&lt;p&gt;But then he decided: if I were a character who really cared about understanding insurance thoroughly, who would want to have an informed conversations about it… So he became that character and called up his insurance company. Apparently, they’d never talked to someone so well-researched on their contract.&lt;/p&gt;

&lt;p&gt;And that’s the thing, we kind of need to do this throughout our day. When you’re taking something live, you’re not the “ship fast” product engineer anymore. You have the right to say no, the right to say this has to be done slower because of these risks. Your responsibility is to make sure production is stable and things will continue to work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The $9,999 skill #
&lt;/h2&gt;

&lt;p&gt;There’s this &lt;a href="https://www.smithsonianmag.com/history/charles-proteus-steinmetz-the-wizard-of-schenectady-51912022/" rel="noopener noreferrer"&gt;great story about Charles Steinmetz&lt;/a&gt; and Henry Ford. Ford’s engineers couldn’t fix a generator problem, so they called in Steinmetz. He spent two days just listening to the generator and scribbling calculations. Then he climbed up, made a chalk mark, and told them to replace sixteen windings at that exact spot. It worked perfectly.&lt;/p&gt;

&lt;p&gt;When Ford got the $10,000 invoice, he asked for an itemized bill. Steinmetz sent back:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Making chalk mark: $1&lt;/li&gt;
&lt;li&gt;Knowing where to make mark: $9,999&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And think about what Steinmetz did: he could have torn the whole generator apart, called in a team of engineers, or tried a dozen different approaches. Instead, he recognized this was a moment for careful analysis. He spent time listening, thinking, calculating. He put on his expert diagnostician hat, not his collaborative problem-solver hat or his hands-on mechanic hat.&lt;/p&gt;

&lt;p&gt;And this is it exactly. Knowing where to make the mark, &lt;strong&gt;knowing which hat to wear when, that’s the $9,999 skill.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But it’s not just about perspective: each hat comes with different expectations, different powers, different rights, and different responsibilities. The production guardian has the authority to halt deployments. The incident responder can stop all feature work immediately. The planning hat carries the responsibility to think long-term even when it slows things down. When you put on a hat, you’re not only changing how you think and approach the situation: you’re claiming the legitimate authority that comes with that role.&lt;/p&gt;

&lt;p&gt;I think that we often fail not because we lack skills, but because we’re wearing the wrong hat for the moment. Or worse, we’re trying to wear all the hats at the same time.&lt;/p&gt;

&lt;p&gt;The product engineer hat wants speed. The production guardian hat wants stability. The incident responder hat wants recovery. The planner hat wants predictability. These aren’t compatible mindsets, you can’t optimize for all of them simultaneously. The goal is to negotiate productively across them, which is hard as one person, and, this is also why working through problems with others is so powerful.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;THE INCOMPATIBLE MINDSETS
Product Engineer 
 → Wants speed (ship it yesterday)
Production Guardian
 → Wants stability (safety today, here tomorrow)
Incident Responder
 → Wants recovery (fix it now)
Planner 
 → Wants predictability (sustainable pace)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So here’s what I’ve been trying to do, or rather, what I should start doing: be explicit about which hat I’m wearing. Right now I say things like “okay, from a stability POV” before raising concerns about deployment risks. But I should actually say, “let me put on my &lt;strong&gt;production guardian hat&lt;/strong&gt; for a second.” It helps others understand which perspective I’m bringing, and it helps me focus on what matters for that role.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tying it on #
&lt;/h2&gt;

&lt;p&gt;I think there’s more to the hats we wear throughout the day because it’s not just at work: supporting partner, fun uncle, mentor, learner. Each comes with different expectations, powers, and responsibilities.&lt;/p&gt;

&lt;p&gt;But for now, I’ll leave you with this: What hat are you wearing right now? What are the expectations that come with it? What responsibilities? And more importantly, is it the right hat for what you’re trying to do?&lt;/p&gt;

&lt;p&gt;Because understanding when to switch might be one of the most underrated skills we need. I’m currently convinced that being intentional about our roles, knowing which hat we’re wearing and when to change it, that makes a difference. Not between being good or great, but between solving the right problems and creating new ones.&lt;/p&gt;

&lt;p&gt;What would change my mind is if someone showed me that this context-switching has too much overhead. But, I think these aren’t the context switches we usually complain about, the ones that kill our flow when we jump between meetings and deep work. These switches are within the same context we’re already working in. We’re just tilting our perspective, changing how we evaluate the situation. And in my experience, the cost of wearing the wrong hat is far higher than the cost of being intentional about switching.&lt;/p&gt;

</description>
      <category>thinking</category>
      <category>roles</category>
      <category>leadership</category>
      <category>agile</category>
    </item>
    <item>
      <title>Working with Go's test cache on CI — be fast by avoiding work, while doing the important work</title>
      <dc:creator>Björn Andersson</dc:creator>
      <pubDate>Mon, 07 Jul 2025 13:50:00 +0000</pubDate>
      <link>https://dev.to/gaqzi/working-with-gos-test-cache-on-ci-be-fast-by-avoiding-work-while-doing-the-important-work-21kd</link>
      <guid>https://dev.to/gaqzi/working-with-gos-test-cache-on-ci-be-fast-by-avoiding-work-while-doing-the-important-work-21kd</guid>
      <description>&lt;p&gt;I was trying to speed up our slow CI by caching Go builds. The easy win was caching Go’s module downloads (via &lt;code&gt;GOPATH&lt;/code&gt;), but when I added &lt;code&gt;GOCACHE&lt;/code&gt; for the build cache, I got a pleasant surprise: the tests were caching too. 🥳&lt;/p&gt;

&lt;p&gt;I shared the change for review, and a colleague raised a great point: “What about our black box integration tests?” These tests hit APIs and external services that Go can’t track as dependencies. If they cache when they shouldn’t, we might miss real failures: the tests would pass because they didn’t re-run, not because the code actually works.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fundamental Problem #
&lt;/h2&gt;

&lt;p&gt;When my colleague warned me about integration test caching, I realized we had a bigger problem than just my PR. How could I fix this across our entire org? We’ve got ~250 repos, and asking every team to remember special flags or change their test execution wasn’t going to fly. I needed something that would just work everywhere with minimal changes.&lt;/p&gt;

&lt;p&gt;The fundamental issue: our black box integration tests don’t “declare their dependencies” to the Go compiler, so it doesn’t know that something the test is critically dependent upon has changed and requires a rerun (and practically, neither do we really), because they test network services and external binaries that Go has no visibility into. I always have to run these tests.&lt;/p&gt;

&lt;p&gt;I wanted the caching benefits without the risk, ideally with minimal changes since we have lots of codebases that could benefit from this caching improvement. Since our black box integration tests use a shared internal library, I was hoping to find a solution I could implement once there rather than asking teams to modify individual tests or change how they execute them.&lt;/p&gt;

&lt;h2&gt;
  
  
  So… How Do I Make This Work? #
&lt;/h2&gt;

&lt;p&gt;I started by looking for the obvious solutions, there’s probably a flag to ignore the test cache, right? And there were two straightforward options: &lt;code&gt;go clean -testcache&lt;/code&gt; and &lt;code&gt;--count=1&lt;/code&gt;. But here’s the thing, both of them throw away ALL test caching, which felt like using a sledgehammer when I needed a scalpel.&lt;/p&gt;

&lt;p&gt;Then I remembered reading something about environment variables, and files, affecting test caching. I went into &lt;code&gt;go help test&lt;/code&gt; and I remembered right, tests that read environment variables get invalidated when those variables change, so since this is about CI, and I know that CI systems give us unique commit SHAs as env vars… and we have a shared library to help write black box integration tests… so I can make the fix once in that library and everyone gets this benefit!&lt;/p&gt;

&lt;p&gt;Alright, that gives me three options, how do they compare?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simple Option: &lt;code&gt;go clean -testcache&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pro: Dead simple - add one line to your CI config, no test changes needed&lt;/li&gt;
&lt;li&gt;Con: Zero caching benefit for tests&lt;/li&gt;
&lt;li&gt;When to use: Safest solution that still gives you build benefits without changing scripts or tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This works by creating &lt;a href="https://github.com/golang/go/blob/665af869920432879629c1d64cf59f129942dcd6/src/cmd/go/internal/test/test.go#L844-L848" rel="noopener noreferrer"&gt;a file with the current Unix time in nanoseconds&lt;/a&gt; and then, whenever Go runs tests, it checks if the cached test is newer than that timestamp. I appreciate the simplicity: the cache cleaner doesn’t need to understand which cached items are tests (and there are only hashes in that folder), it just sets a “tests are invalid after this moment” marker and the code skips it or not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explicit Option: &lt;code&gt;--count=1&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pro: Granular control per &lt;code&gt;go test&lt;/code&gt; invocation&lt;/li&gt;
&lt;li&gt;Con: Need to change test execution and remember it everywhere, easy to miss (especially in monorepos with many go.mods)&lt;/li&gt;
&lt;li&gt;When to use: Only some tests need cache invalidation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the one you’ll see when people ask how to make Go not cache tests, for our situation not super useful, but mentioning it for completeness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Elegant Option: Environment Variables&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pro: Automatic cache invalidation on CI when needed, maximum caching benefit when possible&lt;/li&gt;
&lt;li&gt;Con: Requires thoughtful test design&lt;/li&gt;
&lt;li&gt;When to use: You have enough tests that the speedup matters and you’re willing to be intentional about cache invalidation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or laid out visually:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Changes Needed&lt;/th&gt;
&lt;th&gt;Test Caching&lt;/th&gt;
&lt;th&gt;Safety&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;go clean -testcache&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CI config only&lt;/td&gt;
&lt;td&gt;❌ None&lt;/td&gt;
&lt;td&gt;✅ Safest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--count=1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Every test invocation&lt;/td&gt;
&lt;td&gt;❌ None&lt;/td&gt;
&lt;td&gt;✅ Safe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Environment variables&lt;/td&gt;
&lt;td&gt;Shared code/library once&lt;/td&gt;
&lt;td&gt;✅ Full&lt;/td&gt;
&lt;td&gt;✅ Safe*&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;*&lt;em&gt;When implemented correctly&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How the Environment Variable Approach Works #
&lt;/h3&gt;

&lt;p&gt;This works because Go invalidates the entire package’s test cache whenever an environment variable it depends on changes, and most CI systems expose a unique commit SHA as an environment variable. For example,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub Actions: &lt;code&gt;GITHUB_SHA&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Drone CI: &lt;code&gt;DRONE_COMMIT_SHA&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When your integration test reads this variable, Go automatically invalidates the cache for that package whenever you push new code. The key insight: you don’t need to &lt;em&gt;use&lt;/em&gt; the variable meaningfully, just &lt;em&gt;read&lt;/em&gt; it. One thing to keep in mind: consider keeping integration tests in separate packages from unit tests to avoid invalidating unit test caches unnecessarily when only the integration tests need cache invalidation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package integrationtesting

func IsIntegrationTest(t *testing.T) {
    t.Helper()
    // This ensures that we invalidate the cache
    // on CI whenever we have a new git SHA
    _ = os.Getenv("DRONE_COMMIT_SHA")
}

// ... another file relying on integrationtesting

func TestAPIIntegration(t *testing.T) {
    integrationtesting.IsIntegrationTest(t)

    // Your actual integration test
    resp := callAPIEndpoint()
    assert.Equal(t, expected, resp)
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Understanding How It Actually Works #
&lt;/h2&gt;

&lt;p&gt;I was getting worried about edge cases. The Go docs said tests won’t cache if environment variables change, but what exactly did that mean? Would reading an env var in one test invalidate &lt;em&gt;all&lt;/em&gt; tests everywhere? Just that package? What if the variable is read through a library call?&lt;/p&gt;

&lt;p&gt;I did some searching and found the &lt;a href="https://github.com/golang/go/blob/6c3b5a2798c83d583cb37dba9f39c47300d19f1f/src/internal/testlog/log.go#L49-L54" rel="noopener noreferrer"&gt;testlog package&lt;/a&gt;, which is how Go implements the tracking of when env vars are read and files opened. That gave me a good sense of how it should behave, so I made an experiment to validate what I expected from the documentation and the code I found.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Experiment Results #
&lt;/h3&gt;

&lt;p&gt;I created &lt;a href="https://github.com/gaqzi/experiment-go-test-caching" rel="noopener noreferrer"&gt;three test packages&lt;/a&gt; to understand the boundaries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One that reads &lt;code&gt;DRONE_COMMIT_SHA&lt;/code&gt; directly&lt;/li&gt;
&lt;li&gt;One that reads it through a library call&lt;/li&gt;
&lt;li&gt;One that doesn’t read any environment variables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then I ran &lt;a href="https://github.com/gaqzi/experiment-go-test-caching/blob/main/test.sh" rel="noopener noreferrer"&gt;nine scenarios to test my assumptions&lt;/a&gt;: What happens when I set the variable? Does package listing matter (&lt;code&gt;./...&lt;/code&gt; vs manual package lists)? What about &lt;code&gt;go test&lt;/code&gt; with no arguments?&lt;/p&gt;

&lt;p&gt;Key findings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Package-level invalidation&lt;/strong&gt; : All tests in a package get invalidated if &lt;em&gt;any&lt;/em&gt; test reads the variable and the variable changes,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Library calls count&lt;/strong&gt; : Reading env vars through dependencies still invalidates the cache&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Package listing doesn’t matter&lt;/strong&gt; : &lt;code&gt;./...&lt;/code&gt;, manual lists, even &lt;code&gt;./&lt;/code&gt; all cache the same way&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No arguments = no cache&lt;/strong&gt; : &lt;code&gt;go test&lt;/code&gt; without targeting never caches&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File-level targeting = no cache&lt;/strong&gt; : &lt;code&gt;go test file_test.go&lt;/code&gt; also never caches&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The big takeaway: Go runs tests per package, and packages are run in parallel. If any test in the package touches an environment variable, the entire package’s cache depends on that variable’s value, so the cache is invalidated when the value is different on the next run.&lt;/p&gt;

&lt;p&gt;Or as a semi-flowchart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Package reads env var? 
 Yes → Env var value changed? 
 Yes → Cache invalid
 No → Cache valid
 No → Cache valid

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This made me comfortable that the approach was predictable and wouldn’t have surprising edge cases, especially because the way &lt;a href="https://github.com/golang/go/blob/6c3b5a2798c83d583cb37dba9f39c47300d19f1f/src/internal/testlog/log.go#L49-L54" rel="noopener noreferrer"&gt;testlog&lt;/a&gt; works is by simply recording that &lt;em&gt;something&lt;/em&gt; called &lt;code&gt;os.Getenv&lt;/code&gt; with this value, and it doesn’t know which test or from where, just that in the course of running these tests this happened. Nice and simple.&lt;/p&gt;

&lt;p&gt;If you want to explore how Go makes decisions around caching yourself, you can run tests with &lt;code&gt;GODEBUG=gocachetest=1&lt;/code&gt; to see Go’s caching decisions in real time. There are more debugging variables available in &lt;code&gt;go help cache&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Results #
&lt;/h2&gt;

&lt;p&gt;We cut our CI times in half with this caching approach, and I’m confident it’s safe to roll out widely because I understand exactly how it works and I can make the required changes to our shared integration testing library so it will just work for the standard case.&lt;/p&gt;

&lt;p&gt;What I appreciate about Go’s design here is how it avoids clever optimizations in favor of predictable behavior. I knew caching wasn’t just on/off, but I wasn’t sure if there would be complex edge cases to worry about. Instead, Go picks the straightforward solution: package-level invalidation that’s easy to reason about.&lt;/p&gt;

&lt;p&gt;The “bigger packages than you think, but still not huge” philosophy means we get plenty of caching benefit, while keeping the invalidation scope manageable, and if we need finer control, we can always split into more packages.&lt;/p&gt;

&lt;p&gt;And that’s the thing, Go just picks the simple and boring solution that works, it’s why I love working with Go. 😁&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The &lt;a href="https://github.com/gaqzi/experiment-go-test-caching" rel="noopener noreferrer"&gt;full experiment is available&lt;/a&gt; if you want to dig into it yourself.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>internals</category>
      <category>ci</category>
      <category>testing</category>
    </item>
    <item>
      <title>Running effective meetings uses the same skills as running successful projects — from meeting minutes to project milestones</title>
      <dc:creator>Björn Andersson</dc:creator>
      <pubDate>Sat, 03 May 2025 08:20:00 +0000</pubDate>
      <link>https://dev.to/gaqzi/running-effective-meetings-uses-the-same-skills-as-running-successful-projects-from-meeting-5cp9</link>
      <guid>https://dev.to/gaqzi/running-effective-meetings-uses-the-same-skills-as-running-successful-projects-from-meeting-5cp9</guid>
      <description>&lt;p&gt;You’ve probably sat through your fair share of meetings where time slips away as conversations wander aimlessly, not unlike being dropped into an unfamiliar codebase, with twisting branches all alike.&lt;/p&gt;

&lt;p&gt;A colleague asked for feedback on a meeting they ran, and after sharing my thoughts, I realized my advice about meetings sounded exactly like how I talk about planning projects. This got me thinking: the skills for running good meetings and successful projects are nearly identical.&lt;/p&gt;

&lt;p&gt;Yet somehow, we still treat our meetings like they’re different beasts entirely. Why do so many meetings fail? Usually because we approach them without a clear plan.&lt;/p&gt;

&lt;p&gt;Meetings are often run like debugging without a hypothesis, just throwing log statements everywhere and hoping something works, where you have a list of topics but no clear goals or time constraints. You might cover everything, but that’s more luck than design.&lt;/p&gt;

&lt;p&gt;This is similar to “planning forward” in projects: We start with a feature list without understanding the details, create up-front timelines in Gantt charts that rarely get revised, and postpone integration until the end. We move through tasks sequentially, assuming everything will go right, only to discover problems when time is about to or has already run out.&lt;/p&gt;

&lt;p&gt;Both approaches ignore that time runs out, whether in a 30-minute meeting or a three-month project. Without a plan, meetings go nowhere and projects fall behind.&lt;/p&gt;

&lt;p&gt;In my experience, here’s what both have in common:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gather everything that needs to get done&lt;/li&gt;
&lt;li&gt;Clarify goals for each item&lt;/li&gt;
&lt;li&gt;Group similar things together&lt;/li&gt;
&lt;li&gt;Prioritize the important stuff first&lt;/li&gt;
&lt;li&gt;Estimate how long each section will take&lt;/li&gt;
&lt;li&gt;Guide the work to keep it on track&lt;/li&gt;
&lt;li&gt;Define next steps so everyone knows what’s happening after&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The pieces #
&lt;/h2&gt;

&lt;p&gt;Let’s break down each of these components and see how they apply specifically to meetings:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Gather: Define your scope #
&lt;/h3&gt;

&lt;p&gt;Just as you wouldn’t start coding without requirements, don’t start a meeting without defining what needs covering. List all topics and be realistic about what fits in the allotted time. If your meeting scope looks like your backlog after a year of “we’ll get to it later,” you’re doing it wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Clarify: Set measurable goals for each topic #
&lt;/h3&gt;

&lt;p&gt;For each topic, be clear about what you’re trying to accomplish:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Discuss:&lt;/strong&gt; “We need to decide on auth providers. What criteria should guide our recommendation?”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decision:&lt;/strong&gt; “We recommend Provider A because…”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FYI:&lt;/strong&gt; “We’ve implemented the new provider in staging and learned…”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro tip&lt;/strong&gt; : Prefix each agenda item with one of these categories (Discuss/Decision/FYI) to ground everyone in what you’re trying to accomplish with each topic.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Group: Combine related topics #
&lt;/h3&gt;

&lt;p&gt;Identify when similar items come from different people and combine them. This prevents redundant discussions and gives a clearer picture of what needs attention, similar to combining related user stories into an epic. When several people raise the same issue in different ways, it’s usually important.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Prioritize: Focus on what matters #
&lt;/h3&gt;

&lt;p&gt;Sequence by importance, not by who talks loudest or which item has been sitting on the agenda longest. Start with critical items so when you inevitably run out of time, at least the important stuff got done.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Estimate: Time boxing #
&lt;/h3&gt;

&lt;p&gt;We accept that iteration estimates will be wrong (it’s just a question of how wrong), and meeting time estimates work exactly the same way. Having a clear time target keeps everyone aligned. Be explicit about constraints: “We have 15 minutes for this topic” creates healthy pressure to stay focused.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Guide: Keep discussions on track #
&lt;/h3&gt;

&lt;p&gt;Just like daily standups in project work, regularly check in on your meeting’s progress. Help nudge the meeting along:&lt;/p&gt;

&lt;h4&gt;
  
  
  Monitor progress toward goals #
&lt;/h4&gt;

&lt;p&gt;Just like in daily standups, pay attention to whether the discussion is moving toward your goal. Ask yourself, “Are we just talking, or are we getting closer to making a decision?” If you’re 10 minutes into database options and no one has mentioned the actual requirements, it’s time to refocus.&lt;/p&gt;

&lt;h4&gt;
  
  
  Keep discussions focused #
&lt;/h4&gt;

&lt;p&gt;When someone goes off on a tangent describing an intricate edge case, redirect with: “That sounds like an important edge case. Will this affect the decision we’re trying to make right now? If not, could you chat with the relevant team after this? Right now we need to focus on making our decision.”&lt;/p&gt;

&lt;h4&gt;
  
  
  Provide time checks #
&lt;/h4&gt;

&lt;p&gt;My &lt;a href="https://www.geepawhill.org/2021/04/07/rice-garlic-more-smaller-steps/" rel="noopener noreferrer"&gt;rice’n’garlic advice&lt;/a&gt; is to check in halfway through a conversation and remind everyone of the time left. Sometimes simply saying “We have 7 minutes left to decide on this” creates the right pressure to wrap things up. If needed, quickly restate the goal: “Remember, we just need to agree on which two options to research further, not make the final decision today.”&lt;/p&gt;

&lt;h4&gt;
  
  
  Make realistic time decisions #
&lt;/h4&gt;

&lt;p&gt;Be realistic about whether you can finish in the time you have. If a 15-minute agenda item is turning into a 45-minute discussion, decide whether to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extend the current meeting (if everyone can stay)&lt;/li&gt;
&lt;li&gt;Schedule a follow-up with just the key stakeholders&lt;/li&gt;
&lt;li&gt;Assign someone to gather more data and come back next time&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. Next steps: Ensure clear outcomes #
&lt;/h3&gt;

&lt;p&gt;Don’t let topics end without everyone knowing the outcome. For each item, ensure everyone knows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is it done or still open?&lt;/li&gt;
&lt;li&gt;Who owns any follow-up actions?&lt;/li&gt;
&lt;li&gt;When should we expect progress?&lt;/li&gt;
&lt;li&gt;How will we track it?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Capture this in your meeting notes. Don’t rely on memory. Write down the decisions, owners, and deadlines so our future selves can thank us.&lt;/p&gt;

&lt;h2&gt;
  
  
  In practice #
&lt;/h2&gt;

&lt;p&gt;Different meetings need different approaches, but a well-run meeting follows the same meta structure. This structure works for all kinds of meetings: one-on-ones, planning sessions, even technical architecture reviews, because the topics and participants change, but the structure that makes meetings effective doesn’t.&lt;/p&gt;

&lt;p&gt;Let’s see how this structure looks in practice with a couple of common meeting types.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrospectives #
&lt;/h3&gt;

&lt;p&gt;Retros help teams reflect on what worked, what didn’t, and what to improve, much like code reviews but for your processes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gather&lt;/strong&gt; : Have everyone add topics to a shared retrospective board&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clarify &amp;amp; Group&lt;/strong&gt; : Cluster related topics to understand common themes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prioritize&lt;/strong&gt; : Vote on which issues will have the most impact to address&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Estimate &amp;amp; Guide&lt;/strong&gt; : Timebox discussions, default 3 minutes per topic, explicitly decide to extend or move on&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next Steps&lt;/strong&gt; : Capture clear action items, owners, and timelines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro tip&lt;/strong&gt; : Seeing the same issues iteration after iteration? Try a &lt;a href="https://www.thoughtworks.com/en-au/insights/blog/reverse-retrospective-part-1" rel="noopener noreferrer"&gt;reverse retrospective&lt;/a&gt; where you start with known problems and dedicate the entire session to brainstorming solutions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recurring team meetings #
&lt;/h3&gt;

&lt;p&gt;Regular meetings work best with a consistent structure, like good software needs a reliable architecture.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gather&lt;/strong&gt; : Maintain a living document where people add items between meetings, plus time at the start to add more&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prioritize&lt;/strong&gt; : Critical conversations happen first, not just what’s been on the list longest&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clarify&lt;/strong&gt; : Define each topic’s goal and intended outcome (FYI, discussion, or decision-making)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Estimate&lt;/strong&gt; : Allocate time to topics based on importance and complexity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guide&lt;/strong&gt; : Check progress mid-topic with “Are we getting closer to our goal?”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next Steps&lt;/strong&gt; : Note who’s doing what by when&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro tip&lt;/strong&gt; : For complex topics, try a &lt;a href="https://medium.com/swlh/the-silent-meeting-manifesto-v1-189e9e3487eb" rel="noopener noreferrer"&gt;silent meeting&lt;/a&gt; approach where everyone reads and comments on a shared document before discussion. This helps people think deeply, solve quick questions in writing, and prevent a few voices from dominating.&lt;/p&gt;

&lt;h2&gt;
  
  
  The meta-skill #
&lt;/h2&gt;

&lt;p&gt;Running a good meeting uses the same mental muscles as running a good project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scope definition is like requirements gathering&lt;/li&gt;
&lt;li&gt;Timeboxing topics is like defining iterations&lt;/li&gt;
&lt;li&gt;Progress checks are like standups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you can’t keep a 30-minute meeting on track, how will you keep a three-month project on track? Both require the same core skills:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clear Goals&lt;/strong&gt; : “We want to discuss database options” is as useless as “We want to build a better app.”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Risk Management&lt;/strong&gt; : Put risky, important topics first, whether in meetings or project timelines.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Progress Monitoring&lt;/strong&gt; : Regularly ask: “Are we moving toward our goal or getting sidetracked?”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexibility with Discipline&lt;/strong&gt; : Sometimes you need to extend a meeting or an iteration, but do it consciously, not by default.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Follow-through&lt;/strong&gt; : Track action items like you track bugs, they’re just as important.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I wonder if running meetings could be good practice for running projects? The skills are similar, but the feedback cycle is much shorter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion #
&lt;/h2&gt;

&lt;p&gt;Every engineer knows that a well-designed system needs both good architecture and regular maintenance. Your meetings are no different.&lt;/p&gt;

&lt;p&gt;By applying the same structured thinking to your meetings that you use in your code (defining clear requirements, managing scope, prioritizing effectively, and documenting outcomes), you transform the meetings in your calendar into productive work sessions.&lt;/p&gt;

&lt;p&gt;In my experience, these skills compound nicely. I bet you’ll get better at delivering focused projects as you get better at running focused meetings.&lt;/p&gt;

&lt;p&gt;So before you schedule your next meeting, run it through the same mental checklist you’d use for planning a project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have you gathered topics and defined what you want from each one?&lt;/li&gt;
&lt;li&gt;Have you prioritized what matters most?&lt;/li&gt;
&lt;li&gt;Can this all get done in the time you have?&lt;/li&gt;
&lt;li&gt;Do you have a plan to keep discussions on track?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep in mind that guiding meetings is a lot like incident response. You can plan all you want, but you need to react to what’s actually happening. This framework gives you a starting point, but the real magic happens when you apply it in the moment. Start small by focusing on timeboxing discussions or defining clear outcomes. The structure matters, but how you adapt when the sewage hits the aerowatt generator is what really counts.&lt;/p&gt;

&lt;p&gt;If not, refactor before you commit.&lt;/p&gt;

&lt;p&gt;Efficient meetings aren’t magic. They’re just good engineering applied to communication.&lt;/p&gt;

</description>
      <category>meetings</category>
      <category>planning</category>
      <category>agile</category>
      <category>facilitation</category>
    </item>
    <item>
      <title>Day-to-day automation using Alfred on your Mac — reducing TOIL outside of your DevOps practice</title>
      <dc:creator>Björn Andersson</dc:creator>
      <pubDate>Mon, 15 Apr 2024 11:15:00 +0000</pubDate>
      <link>https://dev.to/gaqzi/day-to-day-automation-using-alfred-on-your-mac-reducing-toil-outside-of-your-devops-practice-2840</link>
      <guid>https://dev.to/gaqzi/day-to-day-automation-using-alfred-on-your-mac-reducing-toil-outside-of-your-devops-practice-2840</guid>
      <description>&lt;p&gt;I try to be aware of where I have friction in my day-to-day when working at my computer, keeping an eye out for &lt;a href="https://sre.google/sre-book/eliminating-toil/" rel="noopener noreferrer"&gt;TOIL to remove.&lt;/a&gt; Whether it’s from manually repeated actions, or from differing behaviors across apps and services I use. When I identify any of these I try to spend some small amount of time automating or changing how I work to improve.&lt;/p&gt;

&lt;p&gt;All of these things don’t necessarily make a lot of sense from how much time I save, but, it also makes me happy to spend a bit of time improving my environment, and spending a bit of time to make me happy is good enough for me.&lt;/p&gt;

&lt;p&gt;I view doing these kinds of small workflow improvements like a &lt;a href="https://en.wikipedia.org/wiki/Kata#Outside_martial_arts" rel="noopener noreferrer"&gt;kata&lt;/a&gt; because it improves my automation/scripting skills and encourages me to think about how I work. I usually give myself 10-20m to try and make these kinds of improvements just so I know how much time to spend. Just don’t go overboard. XKCD, as always, have a comic to illustrate the downside of going too far. 🙂&lt;/p&gt;

&lt;p&gt;&lt;a href="https://xkcd.com/1319" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2ru1gmcuqcpwtnr67r4.png" alt="‘Automating’ comes from the roots ‘auto-’ meaning ‘self-’, and ‘mating’, meaning ‘screwing’." width="404" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Alfred and why is it an app I’m focusing on? #
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://alfredapp.com/" rel="noopener noreferrer"&gt;Alfred&lt;/a&gt; is an application launcher but oh-so-much-more. It connects with macOS and the Workflows contains a lot of extensions that allow you to interact with all kinds of programs, websites, etc.&lt;/p&gt;

&lt;p&gt;A big part of what Alfred has helped me create is a more unified experience across the apps and websites I use. I have moved some operations that behave differently in different apps into Alfred because then I can focus on what I need to do and then use Alfred to provide consistency (and as I’ve been told, “consistency is good even outside the bathroom”).&lt;/p&gt;

&lt;p&gt;Now, let’s look at how I use Alfred.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built-in functionality #
&lt;/h2&gt;

&lt;p&gt;These are features that don’t require anything extra to install and use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Open an app #
&lt;/h3&gt;

&lt;p&gt;Alfred’s starter feature is the application launcher, and it means you summon it with a keybinding and type the name of the app you want to start and voilà. I have bound the keyboard shortcut to &lt;code&gt;cmd+space&lt;/code&gt; and replaced the built-in Spotlight search.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F01-open-app.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F01-open-app.png" title="Opening Firefox in Alfred" alt="Opening Firefox in Alfred" width="716" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Spell / define #
&lt;/h3&gt;

&lt;p&gt;There are certain words I rarely get right (continuous) and some words are spelled very differently from how they sound. Summon Alfred and&lt;code&gt;spell &amp;lt;word&amp;gt;&lt;/code&gt; and you’ll have suggestions that often will go right. And if you don’t find it, replace &lt;code&gt;spell&lt;/code&gt; with &lt;code&gt;google&lt;/code&gt; and see if Google knows better. Hit enter to copy the correct spelling to the clipboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F02-spell-continuous.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F02-spell-continuous.png" title="Finding the correct spelling of continuus" alt="Finding the correct spelling of continuus" width="709" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And &lt;code&gt;define&lt;/code&gt; is the same thing but for dictionary lookup because you have some word you’re unsure what it means, or because you’re wondering if someone was trying to call you something you with some subtle nuance to a word. 😉 Hit enter to open the definition in macOS’s dictionary app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F03-define-laggard.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F03-define-laggard.png" title="Define 'laggard'" alt="Define 'laggard'" width="710" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Calculator #
&lt;/h3&gt;

&lt;p&gt;You can give it an expression and when you hit enter the result goes into the clipboard. I often end up using this instead of opening a Python console on the CLI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F04-calculator.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F04-calculator.png" title="Adding some numbers together" alt="Adding some numbers together" width="709" height="117"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom web search #
&lt;/h3&gt;

&lt;p&gt;A custom web search allow you to quickly open a web browser at a particular website with whatever value you’ve typed into Alfred which &lt;em&gt;doesn’t have to be a search engine or even a search page.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To configure a custom web search summon Alfred and hit &lt;code&gt;cmd+,&lt;/code&gt; to open the settings page. Go into the &lt;code&gt;Features&lt;/code&gt; tab and click on &lt;code&gt;Web Search&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F05-web-search-listing.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F05-web-search-listing.png" title="Alfred's setting Features -&amp;gt; Web Search highlighted" alt="Alfred's setting Features -&amp;gt; Web Search highlighted" width="751" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some example search engines I have made:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jira: &lt;code&gt;https://jira.example.com/browse/{query}&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;This isn’t a search but rather the view this ticket. Because I often get a ticket id (either from a commit message or someone rattling it off in a meeting) and this way I can open it quickly&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Confluence: &lt;code&gt;&lt;a href="https://confluence.example.com/dosearchsite.action" rel="noopener noreferrer"&gt;https://confluence.example.com/dosearchsite.action&lt;/a&gt;? queryString={query}&lt;/code&gt;
&lt;/li&gt;

&lt;li&gt;Wordnik: &lt;code&gt;&lt;a href="https://wordnik.com/words/%7Bquery%7D" rel="noopener noreferrer"&gt;https://wordnik.com/words/{query}&lt;/a&gt;&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;So I can find synonyms and other alternatives for words. Often use this when I want to find a good name for something which has been inspired by &lt;a href="https://signalvnoise.com/svn3/hunting-for-great-names-in-programming/" rel="noopener noreferrer"&gt;Hunting for great names in programming&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Pypi: &lt;code&gt;&lt;a href="https://pypi.org/project/%7Bquery%7D" rel="noopener noreferrer"&gt;https://pypi.org/project/{query}&lt;/a&gt;&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;To look up python packages
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F06-web-search-example-config.png" title="Example setup of the Confluence search engine" alt="Example setup of the Confluence search engine" width="676" height="406"&gt;
## Working with other applications #
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Alfred has ended being the tool that brings my apps to focus and smoothes over differences between apps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Give my most common apps a keybinding #
&lt;/h3&gt;

&lt;p&gt;Instead of &lt;code&gt;cmd+tab&lt;/code&gt; between the various apps I’m using I have bound specific keybindings to my most used app, so I can quickly swap between them. &lt;a href="https://dev.to/rstacruz/switching-apps-slow-down-my-productivity-and-how-i-fixed-it-2anb"&gt;Hat tip to Rico Sta. Cruz&lt;/a&gt;who blogged about this a couple of years ago and who I picked it up from.&lt;/p&gt;

&lt;p&gt;The big benefit I have found here is just the ease of being mid-thinking and wanting to switch back to another app, whether it’s to jot down a quick note, to finish that Regex you were visualizing on &lt;a href="https://regex101.com/" rel="noopener noreferrer"&gt;Regex 101&lt;/a&gt;, or to get back to Slack to paste that thing your colleague asked for. It feels so seamless compared to tabbing between.&lt;/p&gt;

&lt;p&gt;This is using &lt;a href="https://www.alfredapp.com/workflows/" rel="noopener noreferrer"&gt;Alfred’s Workflows&lt;/a&gt;, and they’re part of their advanced set of options. You can do keybindings that work across all of macOS as well as actions based on what you’re typing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F07-app-shortcuts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F07-app-shortcuts.png" title="The custom app shortcuts workflow" alt="The custom app shortcuts workflow" width="607" height="695"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Spotify controller #
&lt;/h3&gt;

&lt;p&gt;I have been using these keybindings since before Alfred, in Quicksilver, and there are other workflows for Spotify but since I had these I never bothered installing anything else.&lt;/p&gt;

&lt;p&gt;The cool extra in this workflow is that I added a keyword to open the current playing song on &lt;a href="https://genius.com" rel="noopener noreferrer"&gt;Genius.com&lt;/a&gt; because I like reading the lyrics.&lt;/p&gt;

&lt;p&gt;This is an example of something where the automation is _far from necessary,_but, I enjoyed adding it. It’s something I do every other week and knowing I can just go straight into the song nearly every time is great.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F08-spotify-keybindings.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F08-spotify-keybindings.png" title="Spotify keybinding and keyword configuration" alt="Spotify keybinding and keyword configuration" width="528" height="710"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My &lt;a href="https://github.com/gaqzi/alfred-workflows/blob/master/Spotify%20keyboard%20shortcuts.alfredworkflow" rel="noopener noreferrer"&gt;Spotify workflow&lt;/a&gt; is on Github if you want to install it, or &lt;a href="https://gist.github.com/gaqzi/b3de88050bf1caaf8d2661233b51a1ae" rel="noopener noreferrer"&gt;here’s a gist&lt;/a&gt;if you’re just curious how I made “open on genius.”&lt;/p&gt;

&lt;h3&gt;
  
  
  Global microphone mute/unmute shortcuts #
&lt;/h3&gt;

&lt;p&gt;I regularly use Google Meet, Slack, and Zoom for talking with people, and these apps all use different shortcuts to mute. So instead of keeping the app focused and remembering the various shortcuts I now just leave myself unmuted everywhere and directly mute/unmute the OS through Alfred. My mic has a visual indicator when it’s on. +I have a notification posted, so I can see the current status on the screen.&lt;/p&gt;

&lt;p&gt;As I started using this workflow I realized that sometimes the microphone bugs out but swapping it between the built-in and back will fix it. So after a while I made a script to help swap as well.&lt;/p&gt;

&lt;p&gt;And finally, I realized that sometimes my virtual soundcard which removes background noise (&lt;a href="https://krisp.ai" rel="noopener noreferrer"&gt;krisp.ai&lt;/a&gt;) hangs and needs to be restarted, so another keybinding to quickly restart the soundcard.&lt;/p&gt;

&lt;p&gt;The only downside of this workflow is that others can’t as clearly see when I want to speak by unmuting myself in the current app, so in those rare cases I’ll use the mute in the app itself. Because optimizing my workflow shouldn’t come at the pain of everyone else, we live in a society. 🙂&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F09-mic-switch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F09-mic-switch.png" title="The mic switch workflow setup" alt="The mic switch workflow setup" width="587" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This &lt;a href="https://github.com/gaqzi/alfred-workflows/blob/master/Toggle%20mute%20mic.alfredworkflow" rel="noopener noreferrer"&gt;mute/unmute workflow&lt;/a&gt; is available on Github, and &lt;a href="https://gist.github.com/gaqzi/f299047706c10b2616ba15c94cabf1fe" rel="noopener noreferrer"&gt;here’s a gist&lt;/a&gt; if you want to see the toggle code. My dotfiles got the &lt;a href="https://github.com/gaqzi/conf/blob/master/bin/swap-mic-input" rel="noopener noreferrer"&gt;swap mic script&lt;/a&gt; and the &lt;a href="https://github.com/gaqzi/conf/blob/master/bin/%2Crestart-krisp" rel="noopener noreferrer"&gt;restart krisp script&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Improvement to my day-to-day workflow #
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Text replacement / snippets #
&lt;/h3&gt;

&lt;p&gt;Snippets are short pieces of text that expand into something else. It can be a static string, or it can be dynamic and I use both kinds as I work. For me they fall into these categories&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;“Named paste”, things that are hard to remember or unwieldy and are now not&lt;/li&gt;
&lt;li&gt;Dynamic replacement, something that follows a pattern and I want to swap between. Generally these use the clipboard&lt;/li&gt;
&lt;li&gt;Generated inputs, I need the current time in a specific format or some other piece of data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You configure snippets by summoning Alfred and hitting &lt;code&gt;cmd+,&lt;/code&gt; which opens Settings, then go into Features -&amp;gt; Snippets. Snippets work by specifying a keyword, in my default bundle I require that my keywords are prefixed with &lt;code&gt;\\&lt;/code&gt;, meaning that Alfred will expand my snippets if it sees &lt;code&gt;\\&amp;lt;keyword&amp;gt;&lt;/code&gt; and with the example keyword &lt;code&gt;exp&lt;/code&gt; you’d then type &lt;code&gt;\\exp&lt;/code&gt; to add it. If you need to type the exact string for some reason it’s easiest to add a space somewhere before you type the last character and then go back and remove it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F11-snippets-config.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F11-snippets-config.png" title="How to view or create snippets" alt="How to view or create snippets" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My trigger for creating a snippet is finding that I keep typing or pasting the same thing again and again.&lt;/p&gt;

&lt;p&gt;Let’s look at how I use them in a couple of different places.&lt;/p&gt;

&lt;h4&gt;
  
  
  GMail #
&lt;/h4&gt;

&lt;p&gt;Finding emails from “unusual senders:” I label the majority of emails I get at work as they are notifications or otherwise automated emails. So if I get something that isn’t labeled it’s probably a human or something I need to look into, and it can sometimes get hidden in a sea of everything else.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;prefix&amp;gt;gmailn&lt;/code&gt; in the search bar turns into &lt;code&gt;is:inbox is:unread has:nouserlabels&lt;/code&gt; which only shows unread emails in the inbox which doesn’t have a label.&lt;/p&gt;

&lt;p&gt;When I’m processing my labels, which are effectively buckets of things to do, I often go into a label and want to see only the unread items, so I can open the first and then go through them one-by-one. So open the label, focus on the search bar, and type in &lt;code&gt;&amp;lt;prefix&amp;gt;unr&lt;/code&gt; to give me &lt;code&gt;is:unread&lt;/code&gt; and then get to that focus.&lt;/p&gt;

&lt;h4&gt;
  
  
  Jira tickets #
&lt;/h4&gt;

&lt;p&gt;If I’m writing a message on Slack and I need to reference a ticket I think it’s nice to give a link even if I only have the jira ticket ID, so I made a snippet that adds the current clipboard item at the end of my company’s Jira instance in a Markdown link. Now it looks nice where markdown is and the other person doesn’t have to open it up themselves.&lt;/p&gt;

&lt;p&gt;Copy &lt;code&gt;WRK-123&lt;/code&gt; and then type &lt;code&gt;&amp;lt;prefix&amp;gt;jiramd&lt;/code&gt; which replaces it with&lt;code&gt;[WRK-123](https://jira.deliveryhero.com/browse/WRK-123)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The Alfred snippet configuration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[{clipboard:trim}](https://jira.example.com/browse/{clipboard:trim})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F12-snippet-jiramd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F12-snippet-jiramd.png" title="Configuring the jiramd snippet in Alfred" alt="Configuring the jiramd snippet in Alfred" width="706" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Roam Research #
&lt;/h4&gt;

&lt;p&gt;Roam is my notetaking app and where most of my thinking happen and I have a whole slew of replacements for how I work with Roam Research and most of them are to help me keep my workflow consistent (using the right tags) and to make common actions easier and faster.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;prefix&amp;gt;rts&lt;/code&gt; turns into the current time in bold since I practice interstitial journaling. Example &lt;code&gt;**15:03**&lt;/code&gt;. Snippet configuration: &lt;code&gt;**{time:short}**&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;prefix&amp;gt;b&amp;lt;shortcode&amp;gt;&lt;/code&gt; for how I bucket tasks so when I spend time on a particular bucket I can find the things I need to do. I.e. my bucket “Life in Production” (on-call, observability, continuous delivery, etc.) is prefixed with &lt;code&gt;&amp;lt;prefix&amp;gt;bl&lt;/code&gt; and that turns into &lt;code&gt;[🥬]([[Bucket/Life in Production]])&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;prefix&amp;gt;&amp;lt;INITIALS&amp;gt;&lt;/code&gt; to turn into the name of my most frequent collaborators at work, so I can tag what I’ve said to them or a task we need to do.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Emoji search #
&lt;/h3&gt;

&lt;p&gt;Spending a lot of time communicating across continents involves timezones and people rarely hearing your voice, so I have gotten used to peppering my inputs with emojis to help since it’s so easy to come off sounding like an ass otherwise.&lt;/p&gt;

&lt;p&gt;And because some websites or applications don’t have a good search for emoji and this way I only have to learn one keyboard shortcut and normalize it across places. This way I don’t have to remember how Slack named this emoji vs. Miro vs. Google Docs vs. Confluence vs. other random website. I just learn it in Alfred and then paste it straight into the textbox I wanted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F10-search-emoji.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F10-search-emoji.png" title="Searching for the rocket emoji" alt="Searching for the rocket emoji" width="711" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is an external Workflow made by &lt;a href="https://github.com/jsumners" rel="noopener noreferrer"&gt;James Sumners&lt;/a&gt;, and you can download it from the &lt;a href="https://github.com/jsumners/alfred-emoji" rel="noopener noreferrer"&gt;workflow’s Github page.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate uuids on the fly #
&lt;/h3&gt;

&lt;p&gt;As I was writing the tying it up section I realized that I had a recent pain which where I kept jumping between apps to create new UUIDs. I was running the following command on the CLI and then pasting it into some yaml files in my editor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uuidgen | tr '[:upper:]' '[:lower:]' | tr -d '\n' | pbcopy

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So I instead created a new workflow that is triggered by a snippet that runs this for me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F15-snippet-uuidgen.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F15-snippet-uuidgen.png" title="Configuring the uuidgen snippet" alt="Configuring the uuidgen snippet" width="502" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; To make it behave just like a regular snippet you need to configure the &lt;em&gt;Copy to clipboard&lt;/em&gt; output to &lt;code&gt;Automatically paste to the frontmost app&lt;/code&gt; and &lt;code&gt;Mark item as transient in clipboard&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F16-snippet-uuidgen-clipboard-config.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F16-snippet-uuidgen-clipboard-config.png" title="How configure the Copy to clipboard output" alt="How configure the Copy to clipboard output" width="605" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/gaqzi/alfred-workflows/blob/master/uuidgen.alfredworkflow" rel="noopener noreferrer"&gt;uuidgen workflow&lt;/a&gt; is available on Github.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other workflows #
&lt;/h2&gt;

&lt;p&gt;Some other workflows I have installed since they save me time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calculate Anything #
&lt;/h3&gt;

&lt;p&gt;I installed this for two reasons: to quickly translate cooking recipes using imperial units into metric and currency conversion. Super convenient and now I can finally get how much 16 floz is in ml (473.176) without needing to go online.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F13-calculate-anything.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F13-calculate-anything.png" title="Calculate Anything converting 16 floz to ml" alt="Calculate Anything converting 16 floz to ml" width="710" height="111"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By &lt;a href="https://github.com/biati-digital" rel="noopener noreferrer"&gt;Biati Digital&lt;/a&gt; and available in the &lt;a href="https://alfred.app/workflows/biatidigital/calculate-anything/" rel="noopener noreferrer"&gt;Alfred Gallery&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Epoch converter #
&lt;/h3&gt;

&lt;p&gt;There was a time when I kept looking at unix timestamps and needed to quickly get when it was, so copying and then &lt;code&gt;ts &amp;lt;paste&amp;gt;&lt;/code&gt; gave me when it was and&lt;code&gt;ts&lt;/code&gt; without anything will give you the current unix timestamp.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F14-epoch-converter.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsanitarium.se%2Fimg%2F2024%2F04%2F15%2F14-epoch-converter.png" title="Epoch Converter showing the current unix timestamp" alt="Epoch Converter showing the current unix timestamp" width="710" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By &lt;a href="https://github.com/snooze92" rel="noopener noreferrer"&gt;Julien Lehuen&lt;/a&gt; and available in the &lt;a href="https://alfred.app/workflows/julienlehuen/epoch-converter/" rel="noopener noreferrer"&gt;Alfred Gallery&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tying it up and how I figure out what to add #
&lt;/h2&gt;

&lt;p&gt;I hope the above gives you some ideas or inspiration for what you could do to improve your day-to-day computer usage. These are things that I’ve pulled together over years, and similarly I have a &lt;a href="https://github.com/gaqzi/conf" rel="noopener noreferrer"&gt;bin/ folder&lt;/a&gt; with other types of automation I’ve accrued, hehe. 😅&lt;/p&gt;

&lt;p&gt;Now, how have I accrued these things? I generally try to reflect on the work I do and the biggest help to it has been scheduling 30min every Friday to reflect on the week. This session covers everything from updating my &lt;a href="https://jvns.ca/blog/brag-documents/" rel="noopener noreferrer"&gt;brag document&lt;/a&gt; to reflecting on what work I felt I repeated a lot and whether there’s anything there to spend time on in the future. Pretty much, what annoyed me when working and can I do something about it?&lt;/p&gt;

&lt;p&gt;If I come up with something that I can’t deal with right now then I’ll record it in Roam under &lt;code&gt;#hack-idea&lt;/code&gt;, whether it’s Friday or not, and when I feel like hacking on something I’ll look there. Because sometimes you just need something quick to hack on. 🙂&lt;/p&gt;

&lt;p&gt;I’d love to hear what your favorite day-to-day automations are on &lt;a href="https://hachyderm.io/@gaqzi" rel="noopener noreferrer"&gt;Mastodon&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>alfred</category>
      <category>productivity</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
