<?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>Forem: Freddie Carthy</title>
    <description>The latest articles on Forem by Freddie Carthy (@freddiecarthy).</description>
    <link>https://forem.com/freddiecarthy</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%2F198990%2F1a08e3f3-d1c9-4d64-8775-b2c9f26e0ad6.jpg</url>
      <title>Forem: Freddie Carthy</title>
      <link>https://forem.com/freddiecarthy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/freddiecarthy"/>
    <language>en</language>
    <item>
      <title>Use Git and Bash to Automate Your Developer Tooling</title>
      <dc:creator>Freddie Carthy</dc:creator>
      <pubDate>Mon, 28 Dec 2020 21:21:49 +0000</pubDate>
      <link>https://forem.com/freddiecarthy/use-git-and-bash-to-automate-your-developer-tooling-1bab</link>
      <guid>https://forem.com/freddiecarthy/use-git-and-bash-to-automate-your-developer-tooling-1bab</guid>
      <description>&lt;p&gt;If you followed &lt;a href="https://dev.to/freddiecarthy/make-your-dotfiles-portable-with-git-and-a-simple-bash-script-dk9"&gt;part one&lt;/a&gt; of this series you should now have a simple repo with your dotfiles and an &lt;code&gt;install&lt;/code&gt; script you can run from any machine, even if you don't have Git installed locally. However this is fairly limited. &lt;strong&gt;When starting from zero on a new machine there's a plethora of tooling you'll typically want to install&lt;/strong&gt;; things like Git, Yarn, npm, Homebrew, etc. Additionally you'll have to set up your Git authorship. Let's expand our simple &lt;code&gt;install&lt;/code&gt; script so that it handles all of our tooling!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I've set up a &lt;a href="https://github.com/gjunkie/dotfiles-starter-kit"&gt;sample repo here&lt;/a&gt; if you just want to get going.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  1. Install Your Basic Package Managers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;This script assumes you're using a Mac and that you've gone through the first part of the tutorial&lt;/strong&gt;. Much like in part one of this tutorial where we added a list of files we want to take with us from system to system, we'll add a list of our preferred tooling we carry with us wherever we go. In this section we'll have our &lt;code&gt;install&lt;/code&gt; script install Git, Homebrew, and npm.&lt;/p&gt;

&lt;p&gt;First, let's write a function that will install Homebrew. We'll subsequently use it to install Git:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /install
install_homebrew() {
  _process "→ Installing Homebrew"
  /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

  _process "→ Running brew doctor"
  brew doctor
  [[ $? ]] \
  &amp;amp;&amp;amp; _success "Installed Homebrew"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we define a function called &lt;code&gt;install_homebrew&lt;/code&gt; which will install Homebrew from their repository in much the same way we're setting up our &lt;code&gt;install&lt;/code&gt; script here. It will also run &lt;code&gt;brew doctor&lt;/code&gt; to ensure everything is going smoothly (&lt;a href="https://docs.brew.sh/Manpage#doctor-options"&gt;docs&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Alright, now let's write a simple function to install npm using Homebrew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /install
install_node() {
  if ! type -P 'npm' &amp;amp;&amp;gt; /dev/null; then
    _process "→ Installing node"

    curl https://www.npmjs.org/install.sh | sh

    [[ $? ]] \
    &amp;amp;&amp;amp; _success "Installed npm"
  fi
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we'll run both of these functions in our &lt;code&gt;install&lt;/code&gt; function at the bottom of the file. The function should now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /install
install() {
  download_dotfiles
  link_dotfiles
  install_homebrew
  install_node
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Install Your Tooling
&lt;/h2&gt;

&lt;p&gt;OK, we've got a great little script here that will link our dotfiles and install our package managers. &lt;strong&gt;At this point you've got a pretty great setup ready for you to use and install the tools you use every day&lt;/strong&gt;. However we can also have this script do a lot of that for us for tools we use regardless of the system we're using. Now that we've got these package managers installed this should be straightforward.&lt;/p&gt;

&lt;p&gt;Create another file in your &lt;code&gt;/opt&lt;/code&gt; folder called &lt;code&gt;homebrew&lt;/code&gt;. In here list out all Homebrew packages you wish to install in any given computer, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /opt/homebrew
eslint
fzf
ripgrep
git
n
yarn
vim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how things should look now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/dotfiles
  /opt
    files
    homebrew

  /configs
    .gitconfig
    .gitignore
    .bash_profile
    .vimrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Back in our &lt;code&gt;install&lt;/code&gt; script we'll want to write a function that loops through each of these packages and installs them with Homebrew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /install
install_formulae() {
  if ! type -P 'brew' &amp;amp;&amp;gt; /dev/null; then
    _error "Homebrew not found"
  else
    _process "→ Installing Homebrew packages"

    # Set variable for list of homebrew formulaes
    brews="${DIR}/opt/homebrew"

    # Update and upgrade all packages
    _process "→ Updating and upgrading Homebrew packages"
    brew update
    brew upgrade

    # Tap some necessary formulae
    brew tap homebrew/cask-versions
    brew tap homebrew/cask-drivers
    brew tap vitorgalvao/tiny-scripts

    # Store IFS within a temp variable
    OIFS=$IFS

    # Set the separator to a carriage return &amp;amp; a new line break
    # read in passed-in file and store as an array
    IFS=$'\r\n' formulae=($(cat "${brews}"))

    # Loop through split list of formulae
    _process "→ Checking status of desired Homebrew formulae"
    for index in ${!formulae[*]}
    do
      # Test whether a Homebrew formula is already installed
      if ! brew list ${formulae[$index]} &amp;amp;&amp;gt; /dev/null; then
        brew install ${formulae[$index]}
      fi
    done

    # Reset IFS back
    IFS=$OIFS

    brew cleanup

    [[ $? ]] &amp;amp;&amp;amp; _success "All Homebrew packages installed and updated"
  fi
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is pretty well documented, but let's recap. It will first ensure that Homebrew is installed on our system. It sets a variable for our &lt;code&gt;ops/homebrew&lt;/code&gt; file with the packages we want. Further down we loop through each line in the file and installs those packages.&lt;/p&gt;

&lt;p&gt;And now we'll call this function at the end of our &lt;code&gt;install&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /install
install() {
  download_dotfiles
  link_dotfiles
  install_homebrew
  install_node
  install_formulae
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we also have &lt;code&gt;npm&lt;/code&gt; installed we could easily set up a file called &lt;code&gt;opt/npm&lt;/code&gt; and list any packages available via npm there. We'd then just have to define a function similar to &lt;code&gt;install_formulae&lt;/code&gt;, perhaps called &lt;code&gt;install_npm_packages&lt;/code&gt;, and have similar logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Final Touches
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;We now have all of our tooling installed and ready to use!&lt;/strong&gt; There's just one more thing we can add to make this truly plug-and-play. We'll want to make sure that Git is ready for use with our email and username. In case you forgot, you have to tell Git who you are in order to start making commits and pushing code! At the top of the &lt;code&gt;install&lt;/code&gt; script let's add a couple of additional variables we'll need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /install
USER_GIT_AUTHOR_NAME: &amp;lt;your github user name&amp;gt;
USER_GIT_AUTHOR_EMAIL: &amp;lt;your github email&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's add another helper function to show us a warning in the event that something goes wrong. Add this near the other helpers we added in part one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_warning() {
  echo "$(date) WARNING:  $@" &amp;gt;&amp;gt; $LOG
  printf "$(tput setaf 3)⚠ Warning:$(tput sgr0) %s!\n" "$@"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's write a function to automatically set your GitHub authorship:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /install
setup_git_authorship() {
  GIT_AUTHOR_NAME=eval "git config user.name"
  GIT_AUTHOR_EMAIL=eval "git config user.email"

  if [[ ! -z "$GIT_AUTHOR_NAME" ]]; then
    _process "→ Setting up Git author"

    read USER_GIT_AUTHOR_NAME
    if [[ ! -z "$USER_GIT_AUTHOR_NAME" ]]; then
      GIT_AUTHOR_NAME="${USER_GIT_AUTHOR_NAME}"
      $(git config --global user.name "$GIT_AUTHOR_NAME")
    else
      _warning "No Git user name has been set.  Please update manually"
    fi

    read USER_GIT_AUTHOR_EMAIL
    if [[ ! -z "$USER_GIT_AUTHOR_EMAIL" ]]; then
      GIT_AUTHOR_EMAIL="${USER_GIT_AUTHOR_EMAIL}"
      $(git config --global user.email "$GIT_AUTHOR_EMAIL")
    else
      _warning "No Git user email has been set.  Please update manually"
    fi
  else
    _process "→ Git author already set, moving on..."
  fi
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is checking for a couple of things. First it checks to see if your global &lt;code&gt;.gitconfig&lt;/code&gt; file already has the author name set. If it does there's nothing else to do here. If it &lt;em&gt;isn't&lt;/em&gt; set it will use the username and email we defined at the top of the file. If you haven't set those either it gives you a warning that you'll need to add GitHub authorship on your own.&lt;/p&gt;

&lt;p&gt;And of course we'll have to call this function after everything else is done:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /install
install() {
  download_dotfiles
  link_dotfiles
  install_homebrew
  install_node
  install_formulae
  setup_git_authorship
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! I hope you found this useful. In the next article we'll explore creating an update script that will pull the latest changes to your dotfiles form GitHub, install any new packages, and source your &lt;code&gt;.bash_profile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you enjoyed this post, &lt;a href="https://twitter.com/freddiecarthy"&gt;I'd love to hear about it on Twitter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>git</category>
      <category>bash</category>
      <category>tooling</category>
      <category>dotfiles</category>
    </item>
    <item>
      <title>Getting Actionable Feedback From Your Team</title>
      <dc:creator>Freddie Carthy</dc:creator>
      <pubDate>Sun, 27 Dec 2020 21:52:38 +0000</pubDate>
      <link>https://forem.com/freddiecarthy/getting-actionable-feedback-from-your-team-7em</link>
      <guid>https://forem.com/freddiecarthy/getting-actionable-feedback-from-your-team-7em</guid>
      <description>&lt;p&gt;&lt;strong&gt;Getting and giving feedback is an incredibly important aspect of being an engineer&lt;/strong&gt;. More so for an Engineering Manager or any type of lead role where their job is to deliver results and help develop careers.&lt;/p&gt;

&lt;p&gt;Most engineers practice some type of feedback loop with their manager. Generally this takes the form of a weekly or bi-weekly check-in. If for some reason you're not already doing this with your team, start doing it &lt;em&gt;now&lt;/em&gt;. &lt;strong&gt;A regular feedback loop is one of the best ways to keep your engineers happy, on track, level them up, and grow as a manager&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Too often I see check-ins and reviews be wasted away where the meeting ventures toward "so, how you doin'?" territory. This doesn't help anyone. Here I’ll outline a routine I've used to ensure that I get and give feedback on a regular cadence, ensure it is feedback you can both act on, and keep track of the progress over time. OK, let's get to it!&lt;/p&gt;

&lt;h2&gt;
  
  
  The One-to-One Check-in
&lt;/h2&gt;

&lt;p&gt;So you're a people manager and you've been having regular check-ins with your team. Let me ask you something, what did you discuss with each one of them two months ago? How was their morale? Were they excited about the projects they were working on? Were they making progress toward their career goals? What was their biggest blocker? Were they happy with how &lt;em&gt;you&lt;/em&gt; were supporting them? &lt;strong&gt;If you can't confidently answer these questions you're doing yourself, your team, and frankly your company, a disservice&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's go over a simple routine to solicit actionable feedback, raise red flags to your leadership team as soon as you see them, and ensure that your team feels taken care of.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Gathering Feedback
&lt;/h3&gt;

&lt;p&gt;In order for check-ins to be successful both you and the engineer must be prepared. &lt;strong&gt;Walking into a meeting with no clue of what you'll talk about is a sure way to waste the meeting time&lt;/strong&gt;. Create a shared document between you and the engineer where you can both add your thoughts and talking points for the meeting. I've used Google Docs and Confluence for this in the past. Really, anything will work so long as you can make it visible to just the engineer and yourself. List out three to five open-ended questions. Some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What happened over the past 2 weeks that you're happy about?&lt;/li&gt;
&lt;li&gt;What happened over the past 2 weeks that you're &lt;em&gt;not&lt;/em&gt; so happy about?&lt;/li&gt;
&lt;li&gt;How could our team be more effective?&lt;/li&gt;
&lt;li&gt;How do you feel about your velocity over the past 2 weeks?&lt;/li&gt;
&lt;li&gt;How do you feel about the team's velocity over the past 2 weeks?&lt;/li&gt;
&lt;li&gt;How can I better support you?&lt;/li&gt;
&lt;li&gt;What questions do you have for me?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create a bank of 10-20 of these types of questions that fit your needs or specific situation. Every two weeks pick some new ones from the list and put them at the top of the document. Or perhaps pick the same ones to track progress over time on a specific topic.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Reinforcement
&lt;/h3&gt;

&lt;p&gt;Set a weekly reminder for each team member to fill out the document. This could be whatever fits your workflow best; multiple calendar alerts on the one-to-one invite, Slack reminders, email, etc.&lt;/p&gt;

&lt;p&gt;The goal here is fill out the document with intent and not rush through it. This will ensure the feedback is as complete as possible, and I've found success with reminding the team to fill it out about one week prior to the check-in.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The Discussion
&lt;/h3&gt;

&lt;p&gt;When you finally meet with the engineer, guess what? You now have a ton of stuff to discuss. When I first implemented this strategy my check-ins went from 15 minute coffee walks to 45 minute meaningful conversations. Deep dives into how the team could collaborate better, projects the team wanted to experiment with, or resources I never knew they needed. I was amazed at the level of detail in the feedback I was able to get. &lt;strong&gt;This document is also now a historical record for both of you and can be used to inform your six month and yearly reviews&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can also add an "action items" section to the document (in Confluence these could create Jira tickets) where either you or the engineer can add things to tackle over the next two weeks. When you meet again you can review these items.&lt;/p&gt;

&lt;p&gt;This is just one way of soliciting meaningful feedback from your team. Have you tried any other routines? What has worked well for you?&lt;/p&gt;

&lt;p&gt;If you enjoyed this post, &lt;a href="https://twitter.com/freddiecarthy"&gt;I'd love to hear about it on Twitter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>management</category>
      <category>engineering</category>
      <category>feedback</category>
    </item>
    <item>
      <title>Make Your dotfiles Portable With Git and a Simple Bash Script</title>
      <dc:creator>Freddie Carthy</dc:creator>
      <pubDate>Wed, 23 Dec 2020 04:46:48 +0000</pubDate>
      <link>https://forem.com/freddiecarthy/make-your-dotfiles-portable-with-git-and-a-simple-bash-script-dk9</link>
      <guid>https://forem.com/freddiecarthy/make-your-dotfiles-portable-with-git-and-a-simple-bash-script-dk9</guid>
      <description>&lt;p&gt;Are you getting the most out of your dotfiles? Time and again I see engineers under-utilizing the power of their dotfiles. They either don't maintain a version-controlled set of dotfiles, or they do but they haven't been touched in years. This can lead to a fragmented developer environment between your personal and work computer. &lt;strong&gt;Wouldn't it be cool if you could have a one-line install for your dotfiles and a single command to keep them up-to-date between systems?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My dotfiles are like my digital identity. They serve two primary purposes; they hold all of my settings and I use them to install all of my tooling. This keeps my work and personal computer 100% synced.&lt;/p&gt;

&lt;p&gt;At minimum there's a handful of files that I like to share across systems. These include files like &lt;code&gt;.gitignore&lt;/code&gt;, &lt;code&gt;.gitconfig&lt;/code&gt;, bash aliases, &lt;code&gt;.bash_profile&lt;/code&gt;, &lt;code&gt;.vimrc&lt;/code&gt;, and a number of others.&lt;/p&gt;

&lt;p&gt;There's also several tools that I always use regardless of the system I'm working on; Git, Vim, yarn, npm, and Homebrew to name a few.&lt;/p&gt;

&lt;p&gt;In this series &lt;strong&gt;I'll show you how to supercharge your dotfiles to keep them synced across your machines effortlessly.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Setting things up.
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;This script assumes you're using a Mac&lt;/strong&gt;. First things first you'll need to setup a repo on GitHub (or preferred location) for your dotfiles.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I've set up a &lt;a href="https://github.com/gjunkie/dotfiles-starter-kit"&gt;sample repo here&lt;/a&gt; if you just want to get going.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Clone the repo and &lt;code&gt;cd&lt;/code&gt; into it. Create a folder called &lt;code&gt;/opt&lt;/code&gt;, and in there a file called &lt;code&gt;files&lt;/code&gt; (in the future this folder will also hold a list of tools you use). In that file paste the following (add any dotfiles relevant to you):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /opt/files
configs/.gitconfig    .gitconfig
configs/.gitignore    .gitignore
configs/.bash_profile .bash_profile
configs/.vimrc        .vimrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This list will tell our future &lt;code&gt;install&lt;/code&gt; script to look for the files listed on the left and create symlinks in our home directory with the names on the right. We haven't setup the &lt;code&gt;/configs&lt;/code&gt; folder to hold our dotfiles quite yet, so let's do that next!&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;/configs&lt;/code&gt; folder at the root of the project. This folder is what will hold all of our dotfiles (as listed above). Think of these files as the "source of truth" for each of your dotfiles. For each of the files you can paste in the contents of your current dotfiles to get started. Make a commit and push this baby up! This is how things should look like now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/dotfiles
  /opt
    files
  /configs
    .gitconfig
    .gitignore
    .bash_profile
    .vimrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OK, moving on...&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Creating a simple install script
&lt;/h2&gt;

&lt;p&gt;Now we've got our dotfiles in our &lt;code&gt;/configs&lt;/code&gt; folder and pushed to GitHub. Pretty great! But what we &lt;em&gt;really&lt;/em&gt; want to do is have an easy way to download these dotfiles onto a new system &lt;em&gt;without even having Git installed&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Create a file called &lt;code&gt;install&lt;/code&gt; at the root of the project. We'll need this script to do a couple of things for us:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download the repo and set itself up in the &lt;code&gt;/usr/local/opt&lt;/code&gt; directory. This is because we'll keep our local copy of the cloned repo where we make changes separate from the set of files your machine will use as the "source of truth".&lt;/li&gt;
&lt;li&gt;Symlink our dotfiles in that directory from our home directory.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At the top of the file let's set up a few variables for easy use in our functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /install
#!/usr/bin/env bash
LOG="${HOME}/Library/Logs/dotfiles.log"
GITHUB_USER=your github user name here
GITHUB_REPO=&amp;lt;your github repo name
DIR="/usr/local/opt/${GITHUB_REPO}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Setting the &lt;code&gt;LOG&lt;/code&gt; location to this will ensure that all logs are visible in the macOS Console app. Handy if something goes wrong and you need to check the logs. Make sure to set &lt;code&gt;GITHUB_USER&lt;/code&gt; to your username and &lt;code&gt;GITHUB_REPO&lt;/code&gt; to whatever you're calling your dotfiles repo. Let's also set up a couple of helper functions that will print out some fancy output as our script runs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /install
_process() {
  echo "$(date) PROCESSING:  $@" &amp;gt;&amp;gt; $LOG
  printf "$(tput setaf 6) %s...$(tput sgr0)\n" "$@"
}

_success() {
  local message=$1
  printf "%s✓ Success:%s\n" "$(tput setaf 2)" "$(tput sgr0) $message"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OK, so now we get to the fun part. Let's write a function that downloads our &lt;code&gt;dotfiles&lt;/code&gt; repo so we can use it locally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /install
download_dotfiles() {
  _process "→ Creating directory at ${DIR} and setting permissions"
  mkdir -p "${DIR}"

  _process "→ Downloading repository to /tmp directory"
  curl -#fLo /tmp/${GITHUB_REPO}.tar.gz "https://github.com/${GITHUB_USER}/${GITHUB_REPO}/tarball/main"

  _process "→ Extracting files to ${DIR}"
  tar -zxf /tmp/${GITHUB_REPO}.tar.gz --strip-components 1 -C "${DIR}"

  _process "→ Removing tarball from /tmp directory"
  rm -rf /tmp/${GITHUB_REPO}.tar.gz

  [[ $? ]] &amp;amp;&amp;amp; _success "${DIR} created, repository downloaded and extracted"

  # Change to the dotfiles directory
  cd "${DIR}"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this is doing is creating a &lt;code&gt;/dotfiles&lt;/code&gt; directory at &lt;code&gt;DIR&lt;/code&gt;, downloading a tarball of your latest &lt;code&gt;main&lt;/code&gt; branch, extracting the file, cleaning up, and finally changing your working directory to &lt;code&gt;/usr/local/opt/dotfiles&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now that we've downloaded your dotfiles we need a basic function to grab your dotfiles from the &lt;code&gt;/configs&lt;/code&gt; folder and create symlinks to them in your home directory. Here it is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /install
link_dotfiles() {
  # symlink files to the HOME directory.
  if [[ -f "${DIR}/opt/files" ]]; then
    _process "→ Symlinking dotfiles in /configs"

    # Set variable for list of files
    files="${DIR}/opt/files"

    # Store IFS separator within a temp variable
    OIFS=$IFS
    # Set the separator to a carriage return &amp;amp; a new line break
    # read in passed-in file and store as an array
    IFS=$'\r\n'
    links=($(cat "${files}"))

    # Loop through array of files
    for index in ${!links[*]}
    do
      for link in ${links[$index]}
      do
        _process "→ Linking ${links[$index]}"
        # set IFS back to space to split string on
        IFS=$' '
        # create an array of line items
        file=(${links[$index]})
        # Create symbolic link
        ln -fs "${DIR}/${file[0]}" "${HOME}/${file[1]}"
      done
      # set separater back to carriage return &amp;amp; new line break
      IFS=$'\r\n'
    done

    # Reset IFS back
    IFS=$OIFS

    source "${HOME}/.bash_profile"

    [[ $? ]] &amp;amp;&amp;amp; _success "All files have been copied"
  fi
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks a bit complex, but what's happening here is actually quite simple. It looks at the &lt;code&gt;/opt/files&lt;/code&gt; file we created, which lists each of your dotfiles, and loops through each line. It then creates a symlink in your home directory for each of those pointing to the files in your &lt;code&gt;/usr/local/opt/&amp;lt;repo name&amp;gt;/configs&lt;/code&gt; folder.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Putting it all together
&lt;/h2&gt;

&lt;p&gt;Finally, we need to actually run these functions for things to actually happen. Here's how I like to do that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /install
install() {
  download_dotfiles
  link_dotfiles
}

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

&lt;/div&gt;



&lt;p&gt;Place that snippet at the bottom of your &lt;code&gt;install&lt;/code&gt; file and you're ready to go. &lt;strong&gt;Keep in mind that running this script will replace any dotfiles you've listed in your &lt;code&gt;files&lt;/code&gt; file!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, running the following command in your terminal will execute our script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ bash -c "$(curl -#fL raw.githubusercontent.com/&amp;lt;your github username&amp;gt;/&amp;lt;your dotfiles repo name&amp;gt;/main/install)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the next &lt;em&gt;installments&lt;/em&gt; 😂 we'll expand on this by having it install our tooling as well as setting up an update script.&lt;/p&gt;

&lt;p&gt;If you enjoyed this post, &lt;a href="https://twitter.com/freddiecarthy"&gt;I'd love to hear about it on Twitter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>bash</category>
      <category>git</category>
      <category>github</category>
      <category>dotfiles</category>
    </item>
  </channel>
</rss>
