• I’ve been thinking about this one for a while. Imagine you are the CEO of a company and your competitors are getting ahead of you because they started to use ChatGPT to build their tech. You ask the CTO what’s going on and the CTO says “ChatGPT was not on my job description, so I ignored it”. How would you feel as the CEO? Would you think “Ok, fair enough for not putting it in the job description” or would your thoughts be a bit more… colorful?

    The CEO has no job description other than: “Making the company successful“. The CEO is responsible for everything. If tech fails, it is the CEO’s fault, if accounting is done wrong, it is the CEO’s fault, if marketing wastes money, it is the CEO’s fault. The buck stops there for everything.

    The CTO’s role is exactly that, but just the tech part. The job description should be “Do anything and everything in the tech domain to make the company successful“. Are the servers down? It is the CTO’s fault. Marketing doesn’t have the features they need for a campaign, it is the CTO’s fault. Ransomware destroys operations, it is the CTO’s fault. Tech is spending too much money, it is the CTO’s fault. Too much technical debt, too little, not delivering fast enough, having the wrong kind of skills on the devs, devs are unhappy. Again… it all falls on the CTO’s shoulders. At least this is how I take on the role when I carry the title of CTO.

    This means the CTO is responsible for problems that nobody ever assigned to them. That’s one of the reasons this role is hard. And to be able to do such a role, the CTO needs autonomy, information, access, etc.

    Autonomy is achieved through budget authority. The CTO presents a budget to the CEO and CFO, who approve it and then executes on it. Ideally, then the CTO receives periodic updates from the CFO comparing expenses to budgets, and whether the company has the revenue to back that budget up. If the CTO overspends beyond the tech budget, that’s a problem, but if the company shrinks, that’s a problem too. In both cases the CTO should be proactively thinking about how to cut cost and manage the expenses (before hitting a wall, having a massive layoff, etc).

    Information and access is achieved through having a strong exec team. An exec team that is all on the same page. Including a clear vision from the CEO, a clear understanding on how all other departments are achieving their goals, and how tech helps or hinders them.

    So if there is a job description at all, it should be not for the role of the CTO, but rather for the company itself: what it means to achieve, and how it behaves to empower its C-Suite to further their ambitions.




  • When I was 16 years old or so, one day, my computer didn’t boot. I got a blue screen with some white text-mode error. Something was broken with the file system. This was after being utterly disappointed by Windows 95 and before I became a Linux person, so I was running Windows NT 4.0. I was the only person I knew running that operating system, and thus the only person I knew with an NTFS partition.

    What to do now? That was my only computer, thus I couldn’t get online, smartphones wouldn’t be invented for another decade, I had nobody to ask for help and no tools to run checks on an NTFS partition. That filesystem was quite new back then. I could just blank the hard drive and reinstall Windows NT and all the software. But what about my data? my data!!!

    At 16 years old I learned the lesson that the data is the most valuable and important thing inside my computer. Everything is replaceable. I’m sure if I could see that data now I would life, but for 16-year-old-me, that was my life. I started making backups and since that day I had a personal backup strategy that’s more robust than 90% of the companies I talk to. I have yet to lose a file and I hope to keep it that way. My ex-wife recently recovered from a complete computer failure because she’s following the backup strategy I set up for her.

    One of the things I wonder is, should I have to do a total restore of my data, how do I verify it? I have more than 2 million files. Big chunks could be missing and it might take me years to notice. Because I have so much data to backup, keeping my 3 backups all up to date is hard, so it’s possible that I may have to reconstruct my information piecing things together from the 3 of them. Technically my backup software should be able to do it. But… I’m skeptical.

    This is why every night I have an automatic script that generates a list of all of my files in a text file. That text file gets backed up and unless that files gets permanently and historically lost, I can use it to verify a backup restore. I think my friend Daniel Magliola gave me this idea.

    Since I use Windows (shocker, I know, but try building a Mac workstation with 6 screens and play video games and report back to me), I wrote the script in PowerShell, but since I couldn’t find anything like Linux’s find, the script invokes wsl. Here it is, normally I put it in c:\Users\pupeno\.bin\filelist.ps1:

    echo "Creating list of all files in C:"
    wsl find /mnt/c/Users/pupeno -type b,c,p,f,l,s > C:\Users\pupeno\.all-files.new.txt
    move -Force C:\Users\pupeno\.all-files.new.txt C:\Users\pupeno\.all-files.txt
    echo "Creating lists of all files in D:"
    wsl find /mnt/d -type b,c,p,f,l,s > D:\.all-files.new.txt
    move -Force D:\.all-files.new.txt D:\.all-files.txt
    echo "Creating lists of all files in E:"
    wsl find /mnt/e -type b,c,p,f,l,s > E:\.all-files.new.txt
    move -Force E:\.all-files.new.txt E:\.all-files.txt
    

    And this is how it’s configured in the Task Scheduler to run every night. First run Task Scheduler:

    Once it’s open, create a new task:

    I hope it helps.




  • To convince people to come work for you you offer them, aside from compensation, perks. And you try to have better perks than your competitors (other employers). Brainstorming with my friend Justin a few years ago I came up with what I believe is the ultimate perk and since then I’ve been desperatly trying to find a place to deploy it. I haven’t found a place where I feel even comfortable bringing it up, that’s how far I am from deploying it, so I’m sharing it with the world. If I was running my own company, I’d deploy it in an instance, not giving it a second thought.

    This is the perk: every developer gets a confidentiality-bound personal assistant. There wouldn’t be one PA per developer, because they don’t need nor have enough work that can be delegated to keep one person fully occupied. Instead there would be one for all of the developers (or two, or three… or whatever you need depending on how many devs you have).

    First, I don’t think this would be a very expensive perk, because actually delegating work to a PA is a skill that you have to learn and most developers will not have it. Most developers will not know where to start. But most developers will likely enjoy saying “I have a PA” or “I have a secretary”. Having said that, I would actually run courses for the developers to learn to delegate because…

    It’s a perk that pays for itself. You might think you are paying for extra employees or contractors, but your developers are likely the most expensive salaries in your books. So if they can pass a task to someone else, you are saving money, not spending money. Let’s say a developer needs to arrange a call with a vendor to discuss a technical mater. They have to search for the right person, their contact details, go back and forth over emails. Imagine if the developer just tells their PA “Can you arrange that call?” over a Slack message and that’s the end of it. Back to coding!

    Think about making reservations, making doctors appointments, running errands, making phone calls in general (this is why they should be confidential). Developers tend to hate phone calls. Imagine if they could delegate to someone complaining about a flight ticket that got canceled! I once had a coworker who spent half a day on hold while pretending to code.

    It’s a perk that generates retention: you know why Google pays for food, haircuts, laundry, doctors on-site, etc? It’s because that generates a lot of retention. When you quit Google, you not only need a job, you also need to find a hairdresser, a place to clean your clothes and make doctor’s appointments. They treat you like children and you became as dependent as you were on your parents. I’m not exactly sure where the ethical boundary is here, but offering a free PA feels on the good side of things.

    It’s unique: nobody is doing and I bet nobody will start, even after it’s been proven successful. It’s like private offices: we have the studies to prove that developers need silence to focus and yet we cram them in open office buildings. Private offices, and PAs, are for the three-piece suit executives, not for the lowly developer, so it’s not a perk likely to get devalued when everybody picks it up, because nobody will.

    It’s loud. Imagine when the developer is hanging out with other developers and jokingly says

    > “Have your people call my people to arrange it”

    > “Oh… you don’t have people? I do… this email address and phone number is my PA, just call them… and if you want a PA, come work for us.”

    I’d love to try this some day… 




  • You should not send rejection emails to job candidates when there was no interaction. For example, in the case of rejecting someone just from the application, without a screening call.

    There’s a mantra that good recruiters and hiring managers take on the difficult task of sending rejection emails instead of just ghosting candidates. But I don’t think this should be a black and white decision. Do you agree? Disagree? Please leave a comment with your point of view, I’m intrigued.

    When you had a screening call with the candidate, then the candidate will likely be wondering about the next step, so if the rejection happens at this or any other later stage, then yes, ghosting is extremely rude and you should always send a rejection email and possibly some feedback for the candidate to improve. More on that later.

    If there hasn’t been any interaction, you shouldn’t have your only interaction with the candidate be a rejection. The reason for this is that most of us have, at some point, been desperate, and started applying to lots of jobs hoping that someone would pay us some attention, hoping we may accidentally open a door, and because being homeless is worse that shotgunning job ads. And actually, when the job ads are anonymous bland indistinguishable walls of text, there’s not a lot you can do other than hit apply and move on, so don’t hold it against the candidate.

    The problem is that then this candidate might have hundreds of applications that result in tens of rejections emails. Rejections for roles the candidate forgot about 10 seconds after hitting apply (how long can you remember a non-descript job post about an anonymous company anyway?), so all you are doing by sending the rejection is reminding the candidate that they didn’t get something they forgot they tried to get. When you get tens of these, one after another, it’s emotionally debilitating. It’s no wonder that a candidate might snap at one too many rejections.

    Oh, and about feedback: if you have nothing to say, don’t say anything. If you are going to give feedback, give actionable feedback. Giving someone impossible feedback is a slap in the face. For example, for a few years, I’ve been wanting to have an engineer manager position at a big scale-up or at a big company. When I get rejected and I ask for feedback, most of the time it boils down to “You haven’t been an engineer manager at a big company before”. What am I going to do with that? They might as well tell me “Have you tried being a different person? Have you tried having been born in a different country?” It’s useless and infuriating.




  • I just got an Icom IC-750 with the goal of going out in the open and the first thing I did is try to configure it with my computer because it’s what’s most convenient for me. I like keeping backups of various configurations and being able to go back to them. I’m also working on a project to help set up repeaters in this and others radios.

    Unfortunately, I encountered the error:

    Connected transceiver is not compatible model.

    Check the following:

    • Appropriate programming software for the transceiver is being used.
    • The revision number of the transceiver

    What was confusing is that the CS-705 was correctly seeing my connected IC-705:

    I tried a few things, but long story short, my IC-705 had firmware version 1.31 and I was running CS-705 version 1.11 when only version 1.20 supports firmware 1.31. Now that I upgraded everything works:

    And for the record, I’m running the USB driver version 1.12.

    I find the Icom’s website to download the different versions of the software a bit confusing (especially the interactions between Icom UK and Icom Japan), but you can find it here: https://www.icomjapan.com/support/firmware_driver/?keyword=705&open=tab2&type=5#download_result




  • One of my projects, Unbreach, has a database of more than 600 breaches. These come from haveibeenpwned and they are composed of some metadata, a one-paragraph description, and an image. I wanted to improve these with more content, links to articles, tweets, videos, and some content of my own.

    I decided that a good way to do it would be to move them from the app, which resides at app.unbrea.ch, to the marketing website, which is at unbrea.ch, essentially creating them as blog posts. That way after the blog post is automatically created (when haveibeenpwned ads the breach), I can go in and manually edit it in all the WordPress glory. I thought this was going to take me a few hours, not days.

    Hopefully, with this blog post, it’ll only take you hours. I’ll be using Ruby but it should be trivial to translate it to Python, JavaScript, or any other programming language. Writing the code wasn’t the hard part, understanding the WordPress.com world was.

    WordPress has two different APIs that should be able to accomplish this task, one is the XML-RPC API and the other is the REST API. The XML-RCP API depends on a file called xmlrpc.php and it’s strongly recommended you leave this deactivated because it had a lot of security issues. It’s also old, cumbersome, and possibly on the way out. I didn’t want to use it and I don’t think you should either.

    From what I can gather the REST API is what the admin tool uses, so using it sounds like a safe bet. If you are going to be creating blog posts from an unattended background process, as I do, you’ll find your first obstacle when you read about authentication because it just assumes there’s a browser sending cookies.

    Fear not! There are plug-ins that implement other authentication methods and one of those is the Application Passwords plug-in. Which is now discontinued because it’s been merged into WordPress itself in version 5.6. This sounds promising until you realize the feature seems to be missing in WordPress.com.

    If you search how to create an Application Password on WordPress.com you’ll land in the wrong place. WordPress.com users have an Application Password that’s hidden behind the Two-Step Authentication in Security. This is what it looks like:

    If you are here you are in the wrong place

    What’s going on here? Well, WordPress.com has its own API, which is a REST API, and if you talk to support and WordPress.com they’ll point you to that. I wasn’t a fan of that solution because although I want to use WordPress.com, I don’t want to be tied to it. I want to be able to move to WP Engine or something like that whenever I want.

    That API, similar to the REST API, assumes there’s a human interacting through a third-party application, so it’s not great for unattended processes. Authentication works using OAuth2 which for a background job that just needs an API key I find very annoying. It’s doable but annoying. Well… it’s doable until you enable 2FA and then it’s not doable anymore, and that’s why that specific Application Password exists.

    WordPress.com support also told me that the WordPress REST API is enabled only if you are on a business plan or above.

    So… where’s the Application Password for the REST API then? I don’t know if there’s a link to it anywhere, but you get to it by going to https://example.com/wp-admin/profile.php where example.com is the URL of your blog. That is, add /wp-admin/profile.php to it. On WordPress.com’s defense, it was their support that finally pointed me to it. When you go there you’ll see an old-style profile page:

    The correct place to set up an application password to use the WordPress REST API

    The previous Application Password was tied to the user, this one is tied to the user and the site, so if you have more than one site you’ll need to create one per site.

    And that was the hard part. Once I got that application password things just worked. It’s a straightforward and mostly well-documented API. I’ll share my messy code here anyway (sorry, didn’t have time to clean it up).

    In Ruby I’m using a library called Faraday to talk to APIs. The first thing is creating the Farady object that has the metadata that will be used in all the requests:

    auth_token = "#{Rails.application.credentials.wordpress&.username}:#{Rails.application.credentials.wordpress&.app_pass}"
    auth_token = Base64.strict_encode64(auth_token)
    conn = Faraday.new(url: ENV["WORDPRESS_URL"],
      headers: { "Authorization" => "Basic #{auth_token}" }) do |conn|
     conn.request :json
     conn.response :json
    end
    

    According to Faraday’s documentation, this should have worked as a better way of setting up the authentication details:

    conn.request :authorization,
                 :basic,
                 Rails.application.credentials.wordpress&.username,
                 Rails.application.credentials.wordpress&.app_pass
    

    but for me it didn’t. It was completely ignored. About those two values, Rails.application.credentials.wordpress&.username is the username of the user that will be creating the posts and Rails.application.credentials.wordpress&.app_pass is the corresponding application password. ENV["WORDPRESS_URL"] is the URL of the WordPress site, like https://unbrea.ch/.

    The first thing I need is the id of the category in which these posts will end up. This is very important because they appear on a separate page about breaches and not on the blog and that’s achieved with categories:

    response = conn.get("/wp-json/wp/v2/categories", {search: "Breach", _fields: %w[id name]})
    if response.status != 200
      raise "Unexpected response #{response.status}: #{response.body}"
    end
    category = response.body.find { |category| category["name"] == "Breach" }
    

    Now, if the category doesn’t exist, I want to create it:

    if category.nil?
      response = conn.post("/wp-json/wp/v2/categories") do |req|
        req.body = {name: "Breach"}
      end
      if response.status != 201
        raise "Unexpected response #{response.status}: #{response.body}"
      end
      category = response.body
    end
    

    Then I needed to do the same with tags. In my case, the tags were in a field called data_classes and the code for getting the id of the tag and creating it if it doesn’t exist is very similar:

    tags = data_classes.map do |data_class|
      response = conn.get("/wp-json/wp/v2/tags", {search: data_class, _fields: %w[id name]})
      if response.status != 200
        raise "Unexpected response #{response.status}: #{response.body}"
      end
      tag = response.body.find { |tag| tag["name"] == data_class }
    
      if tag.nil?
        response = conn.post("/wp-json/wp/v2/tags") do |req|
          req.body = {name: data_class}
        end
        if response.status != 201
          raise "Unexpected response #{response.status}: #{response.body}"
        end
        tag = response.body
      end
    
      tag
    end
    

    And finally, we can create the post. I create the content as an HTML snippet which causes WordPress to interpret it as classic content, not as blocks. But that’s fine because it renders well and the first time I edit one of those posts converting them to blocks is two clicks and works perfectly for this simple content.

    content = <<~CONTENT
      <p>#{description}</p>
      <p><!--more--></p>
      <p>Accounts breached: #{pwn_count}</p>
      <p>Breached on: #{breach_date&.strftime("%B %d, %Y")}
      <p>Exposed data: #{data_classes.to_sentence}</p>
      <p>Domain: #{domain}</p>
      <p>Added on: #{added_date.strftime("%B %d, %Y")}</p>
    CONTENT
    
    response = conn.post("/wp-json/wp/v2/posts", {
      title: title,
      content: content,
      excerpt: description,
      status: "publish",
      categories: [category["id"]],
      tags: tags.map { |tag| tag["id"] },
      date_gmt: (breach_date.to_time(:utc) + 12.hours).iso8601.to_s,
      template: "breach-template",
      ping_status: "closed"
    })
    if response.status != 201
      raise "Unexpected response #{response.status}: #{response.body}"
    end
    post = response.body
    

    At this point, I wasn’t done. I wanted these posts to have the image associated with the breach (the logo of the company breached). The first step was downloading it which was a trivial one-liner:

    logo_request = Faraday.new(url: logo_path).get("")
    

    In that code, logo_path is actually a full URL of the file.

    To create media items in WordPress, I needed to encode the post as multi-part, so I ended up creating a separate Faraday object for that:

    multipart_conn = Faraday.new(url: ENV["WORDPRESS_URL"],
      headers: {"Authorization" => "Basic #{auth_token}"}) do |conn|
      conn.request :multipart
      conn.response :json
    end
    

    It should have been possible to use a single Faraday object for all requests, but when you specify multipart, you need to take care of encoding the JSON requests yourself and adding them as one of the parts. This is where I got lazy and just moved on with my work.

    The code for creating the image in WordPress is this:

    extension = File.extname(logo_path)
    file_name = "#{name.underscore.tr("_", "-")}#{extension}"
    content_type = if extension == ".png"
      "image/png"
    else
      raise "Unexpected extension #{extension}"
    end
    media = multipart_conn.post("/wp-json/wp/v2/media", {
      date_gmt: (breach_date.to_time(:utc) + 12.hours).iso8601.to_s,
      status: "publish",
      title: title,
      comment_status: "closed",
      ping_status: "closed",
      alt_text: "Logo for #{title}",
      caption: "Logo for #{title}",
      description: "Logo for #{title}",
      post: post["id"],
      file: Faraday::Multipart::FilePart.new(StringIO.new(logo_request.body), content_type, file_name)
    })
    

    In reality, 100% of the images are PNG so I was ok with such a simplistic approach. When creating the FilePart I wrapped logo_request.body in a StringIO because it already contained the binary data of the image. If you have a local file you can just pass the path to FilePart.new and it just works.

    And now that I had the image, I could set it as the featured image for the post I created earlier:

    response = conn.post("/wp-json/wp/v2/posts/#{post["id"]}", {
      featured_media: media.body["id"]
    })
    if response.status != 200
      raise "Unexpected response #{response.status}: #{response.body}"
    end
    

    The reason why I didn’t create the image before creating the post was so that I could pass the post id to the image and thus the image would be connected to the post. I’m not sure how useful that is.

    And that’s all.

    I wonder if this code should be put in a gem and made reusable. WordPress points to the wp-api-client gem as the Ruby solution, which is read-only and abandoned. There’s also wordpress_v2_api, but I wasn’t a fan of the API (it’s almost like using HTTP directly), it hasn’t been touched in 6 years and I don’t believe it supports writing. I’m half tempted to fork wp-api-client, but does anybody else care, or is it just me? Please leave a comment if this is something you want to use.




  • people sitting on chairs beside their desks in an office

    Is the CTO title tainted? I think so

    by

    ,

    Warning: this is a rant.

    What a CTO does varies from company to company. One way in which the role changes dramatically is with the size of the department. When the tech department is:

    • 1 person, the CTO is mostly a developer.
    • 2 to 10 people, the CTO becomes a manager. They stablish what developers do and executes it.
    • 10 to 50, the CTO becomes a manager of managers. They stablish what developers do and what managers do to execute it.
    • Above 50 the role goes from tactical to strategic. At some point one or more VPs appear that and the CTO is purely strategic.

    There are other ways in which the CTO may vary from company to company. In some the role is purely internal, in others it’s customer facing, or community facing. That depends on what the company does.

    The problem with the CTO role is that the C part of it is not taking seriously

    My experience has been managing up to 20 people so I can’t comment on what the industry is like beyond that. I’m pretty sure some of the things I’m going to be ranting about here are not a problem for the CTOs of 100 people or more. That just can’t be true.

    The problem with the CTO role is that the C part of it is often not taking seriously. Let’s refresh our memory: it stands for Chief. Like the CEO, COO, CFO, being a CTO puts you in the executive team. Even if you are CTO of 1, that means you have (or should have) the authority and the responsibility to execute. That’s the difference between being a coder in a company of 2 and being a CTO in a company of 2.

    An example might help here. Let’s say to develop something needs to be bought: a computer, some software, a development unit of some hardware. Let’s imagine two companies, both which have a CEO but company A has a developer and company B has a CTO.

    The CTO present a decision that is in the best interest to the company based on cash position, cashflow, budget, etc.

    In company A the coder makes the request to the CEO and the CEO decides. In company B, the CTO would instead look at how much cash is in the bank, what the budget for the next quarter/year looks like, take a quick look at the P&L to make sure everything is marching well, make the decision and buy it. Even if there is still an approval process for the acquisition, the CTO doesn’t blindly make a request to the CEO. The CTO present a decision that is in the best interest to the company based on cash position, cashflow, budget, etc. That means the CTO needs access to that information.

    Equally, the CTO has the responsibility to do all that. The CTO leads the technical department, but acts on the best interest of the whole company and failing to do that means failure as a CTO. A CTO cannot hide behind “But that isn’t tech!” as an excuse. The same way that CEOs tend not to take CTOs seriously, and just consider them a cost center that produces code, CTOs tend not to act seriously when they need to step up to the challenge.

    I think a lot of this happens because the CTO title is given to technical co-founders and coders that are excited about building something, but not about all the other tasks CTOing imply. I was a bit like that 12 years ago or so when co-founded Watu, but I had to grow quickly to fill in the shoes of the title.

    Nowadays when I take the role of CTO, these are the responsibilities I take:

    • Producing the product that is core to the company.
    • Running all the technical infrastructure of the company, this includes what sometimes is referred to as IT.
    • Cybersecurity for the whole company.
    • The personal cybersecurity for the CEO and possibly other members of the executive team. This is an odd one, but I’ve seen how disruptive it can be for a company when the CEO is distracted because their email got hacked.
    • Keeping an eye on cash, cashflow, P&L and making sure my department is aligned. If I have a CFO, that’s great, but I can do it myself if it’s simple enough.
    • Work with the other departments to find how technology can enable them to execute their goals faster. This mean generally assisting customer support, marketing, and sales with technology to increase their efficiency.
    • Business continuity: I might not be as good as my CEO as many of their tasks, but if the CEO can’t perform them for whatever reason and there’s nobody else more qualified than me, I’ll jump, whatever it is: selling, raising money, anything and everything.

    […] what I want to do is go around the company and make it awesome by using tech to enhance the efficiency and efficacy of all departments

    My ultimate goal is the success of the company. A good friend of mine has been telling me for years: “You should go for COO roles, that’s why you’ve been doing for years now”. I resisted the idea but I’m started to be onboard. When I join a company as CTO, it’s like I’m told “Go sit in that box and produce code whenever we tell you, try not to make too much noise.” but what I want to do is go around the company and make it awesome by using tech to enhance the efficiency and efficacy of all departments. I want to make the company awesome. I worked at Google, I know what awesome looks like and I want to replicate it.




  • Originally my book was called “Building and Managing Distributed Teams“. I loved that title and people in my social circle loved it too. A friend of mine even told me something along the lines of “I’m so envious I wish I had that title”. And for the two years or so that it took me to write, abandon, restart, abandon again, restart and finally finish the book, I was happy about the title.

    I had three different people ask me what I meant by “distributed”. The first time I ignored it, the third time I panicked.

    As I finished writing the book and it went into proof reading phase, I thought I should try to market it a bit. I’m self publishing, doing everything, including promotion and marketing (hint: I can use your help in getting the word out). During conversations I had three different people ask me what I meant by “distributed”. The first time I ignored it, the third time I panicked.

    I’ve been working from home since the early 2000s. I’ve been building remote/distributed teams and companies since 2011 or so. At the beginning we were called and we called ourselves remote workers. But that soon started to carry a stigma. Companies would have in-office workers and remote workers and remote workers were second class citizens.

    This created a division between being a remote worker and working for a distributed company. The latter was much better.

    The companies that wanted everybody to be remote, the companies that were remote-first, the companies were being remote didn’t mean second class citizen started calling themselves distributed. This created a division between being a remote worker and working for a distributed company. The latter was much better. The movement of distributed work was growing, Automattic, Github, and many other companies were charging ahead… and then the pandemic happened.

    I don’t think the amount of people using the term “distributed” changed during the Covid pandemic, but the amount of people using the term “remote” did and might have turned “distributed” into a rounding error. The natural change of title for my book would have been from:

    Building and Managing Distributed Teams

    to

    Building and Managing Remote Teams

    I wanted to measure this, but I couldn’t find any way to do it. I tried Google Ads but I couldn’t make it work and no other method seemed to even be feasible. One of the problems I had is that I believe polls would be useless, because once you give context to “distributed”, I think everybody understands it, and it might sound better. I wanted to see how they behave in isolation. At any rate, “remote” won in polls, but not overwhelmingly.

    Since I was going to change the title, I may as well consider any and all possible titles, not just a single word change, right? My friend, Justin Megawarne, came up with a very important point: the title doesn’t contain the value proposition. Think of the book “The Four Hour Work Week” by Tim Ferris. If it would have had a descriptive title, like “How to Delegate Work”, he would not have been a bestseller author.

    I tried to find a value proposition name for my book and I gave up

    I tried to find a value proposition title for my book. Companies struggle to hire, grow and manage in-office teams. This is a pain that exists. My friend and advisor works with many companies like that, he wants to recommend them my book, but he knows they don’t believe a book by that title has the solution to their problems. I tried to find a value proposition name for my book and I gave up.

    If I remember correctly it took Tim Ferris weeks of research to come up with the title and cover of his book. I don’t have weeks to dedicate to this, in part because even with the perfect title and cover, without an editor and publisher, with just my own ability to market, it’s not going to have a positive return on investment. And thus, the new title was selected:

    How to Hire and Manage Remote Work

    I did introduce some extra changes. From the conversation with Justin I switched “Building” for “Hiring”, to have the keyword of the pain point a lot of companies are going through. I also asked Ana Bibikova for her opinion since she’s both a marketer and an author. She advised me to switch from imperative phrasing to “How to”. I’m not sure what the effect will be, I don’t have a strong opinion and I trust hers.

    And now, the list of explored and abandoned titles:

    • Building and Managing Distributed Teams (current)
    • Building and Managing Remote Teams
    • Hiring and Managing Remote Teams
    • Find the Best Talent Everywhere
    • Hire the Best and Keep Them
    • Stop Struggling to Hire and Managing Remote Teams
    • Hire Remote: Manage Remote: Stay Remote
    • Hire Remote, Manage Remote, Stay Remote
    • Doing It Better Remotely
    • Hire, Manage, Stay: Remote Working and What It Should Look Like
    • Do Better: Hiring and Managing your Remote Team
    • Remote Teams Done Really Badly (A How Not To)

    I think some of those might come back as titles of blog posts.




  • I’ve hired about 20 developers in my career so far (and I’m looking forward to hire more). When job applications arrive I separate them in three piles: Yes, No, and Maybe. It’s better to do Yes and No piles, but it’s a luxury that I haven’t had (if curious, drop a comment and I’ll write another blog post about it).

    In the No-pile I put all those people that are obviously not a match, people that explicitly tell me they never wrote code before, people outside the time zone target, applications with grammar so bad I can’t understand them, etc.

    […] the most important bit: I find some evidence that they have written code before.

    In the Yes-pile I put all those that show promise. Their application looks good, their profile match and this is the most important bit: I find some evidence that they have written code before.

    The rest of the applicants go to the Maybe-pile. They are not discarded, but I’m going to focus on the ones in the Yes-pile first because I believe I’ll find more successful candidates there than in the Maybe-pile. This doesn’t mean that someone brilliant isn’t in the Maybe-pile. It only means that I couldn’t find any evidence about their potential brilliance.

    Landing on the Maybe-pile is almost as bad as landing on the No-pile

    Here’s the kicker: I never get to the Maybe-pile. I always find all the candidates I want from the Yes-pile. Landing on the Maybe-pile is almost as bad as landing on the No-pile.

    There are many ways in which you can make yourself go from the Maybe to the Yes pile. These are the best ways: blogging about code you write, writing tutorials, contributing to open source software. Having done all of that will not only put you in the Yes-pile, it’ll probably put you at the front.

    But those are things that require a lot of time an effort. There’s another thing that may only require a couple of minutes. If you’ve been using your GitHub account for work or for university, that account has a lot of activity. You may not be able to show code from work and you may not want to show code from university, but you may show the activity. Go to your Public Profile settings and tick “Include private contributions on my profile”:

    This, if you have any private activity, will turn your public GitHub profile from something that looks like a ghost town:

    into something like looks more lively:

    The latter looks like a developer that wrote some code. It will not send you to the top of the Yes-pile, but if the rest of your application looks good, it might be enough to send you to the Yes-pile and it’s a change that requires only a few seconds.

    Now, if you are in the know, you might object that this is completely fakable, and you are right. Yet, I don’t see people faking it. I see lots of empty profiles looking sad and empty, so it’s still a useful signal.

    I’m not trying to find a perfect way to evaluate candidates, I’m trying to find a heuristic to help me find which ones to evaluate first

    Even if some people fake it, I might still continue using the signal. It’s not like you don’t have to pass all the interviews after this anyway. Remember that I’m not trying to find a perfect way to evaluate candidates, I’m trying to find a heuristic to help me find which ones to evaluate first because it’s impossible to evaluate everyone.

    Now, if you decide to fake it, you have two paths. The first one is to just fake, essentially lying about it. That’s a deception. The second is to troll. You can spell out your name or draw something in that part of GitHub. I won’t know if you have real activity or not, your profile won’t look as empty, but at least I know you know enough about coding to pull off that.

    You could argue that because some people wrote the code to make that happen and uploaded to GitHub, all you have to do is find it and run it, and it doesn’t prove that you are above script kiddie. And then again, most applications I have don’t even have script kiddie level of a display of ability, so you may still be coming ahead.




If you want to work with me or hire me? Contact me

You can follow me or connect with me:

Or get new content delivered directly to your inbox.

Join 5,047 other subscribers

I wrote a book:

Stack of copies of How to Hire and Manage Remote Teams

How to Hire and Manage Remote Teams, where I distill all the techniques I’ve been using to build and manage distributed teams for the past 10 years.

I write about:

announcement blogging book book review book reviews books building Sano Business C# Clojure ClojureScript Common Lisp database Debian Esperanto Git ham radio history idea Java Kubuntu Lisp management Non-Fiction OpenID programming Python Radio Society of Great Britain Rails rant re-frame release Ruby Ruby on Rails Sano science science fiction security self-help Star Trek technology Ubuntu web Windows WordPress

I’ve been writing for a while:

Mastodon