diff --git a/course.json b/course.json
index 90b6313..b0e2100 100644
--- a/course.json
+++ b/course.json
@@ -1,19 +1,29 @@
{
"author": {
- "name": "Brian Holt",
- "company": "Neon"
+ "name": "ThePrimeagen",
+ "company": "TheStartup, Try Harder™"
},
- "title": "Next.js Course Starter Kit",
- "subtitle": "for Frontend Masters",
- "frontendMastersLink": "https://frontendmasters.com/courses/complete-react-v9/",
+ "title": "Developer Productivity 2",
+ "subtitle": "become the dev that confuses everyone else",
+ "frontendMastersLink": "https://frontendmasters.com/workshops/dev-prod-2",
"social": {
- "linkedin": "btholt",
- "github": "btholt",
- "twitter": "holtbt",
- "bluesky": "brianholt.me"
+ "twitter": "theprimeagen",
+ "twitch": "theprimeagen",
+ "youtube": "theprimeagen"
},
- "description": "A starter kit for making really amazing courses, optimized for Frontend Masters",
- "keywords": ["your", "Google", "keywords", "here"],
+ "description": "a walkthrough of making your life a bit nicer by understanding how your operating system works",
+ "keywords": [
+ "ThePrimeagen",
+ "Live Coding",
+ "TypeScript",
+ "JavaScript",
+ "Git",
+ "Github",
+ "Algorithms",
+ "DataStructures",
+ "Data Structures",
+ "TS"
+ ],
"productionBaseUrl": "/dev-prod-2",
"csvPath": "./out/lessons.csv"
}
diff --git a/lessons/01-intro/A-intro.md b/lessons/01-intro/A-intro.md
new file mode 100644
index 0000000..564dc19
--- /dev/null
+++ b/lessons/01-intro/A-intro.md
@@ -0,0 +1,139 @@
+---
+title: "Introduction to dev productivity"
+description: "there isn't a right way, but there is my way and its pretty good"
+---
+
+## Dev Productivity
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## WHOAMI
+The name is ThePrimeagen
+
+
+ Twitch
+
+
+
+
+
+
+ ThePrimeTimeagen - Hand crafted meme's and toilet
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## The Goal
+My approach to _my environment_.
+
+or as i like to say: there isn't a right way, but there is my way and its
+pretty good. I only have one thing I optimize which is productivity.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Enqueue Midwit meme
+> BUT WHAT ABOUT i3-gaps, WHAT ABOUT ALL THE RICES
+
+Honestly, I don't care. I just don't care at all. I just want to get where i
+want to be in the fewest amount of keystrokes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## A bit of prereq
+One thing that should be apparent is that i will be approaching this class from
+a unix perspective.
+
+Its not that i don't think windows is good for dev, its just I never use it for
+anything but games.
+
+### Enqueue I Don't even think of you meme
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lessons/01-the-first-section/A-intro.md b/lessons/01-the-first-section/A-intro.md
deleted file mode 100644
index 5e2e514..0000000
--- a/lessons/01-the-first-section/A-intro.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-title: "Introduction"
-description: "The introduction to this course."
-keywords:
- - A course starter
- - Next.js
- - React
- - Brian Holt
----
-
-Hello! And welcome to the Next.js course starter by [Brian Holt][twitter].
-
-![Cat, dog, and rat logo for the course](./images/BRAND-WHearts.png)
-
-This is a course starter specifically made for making online courses and optimized for use with [Frontend Masters][fem].
-
-[twitter]: https://twitter.com/holtbt
-[fem]: https://www.frontendmasters.com
diff --git a/lessons/02-a-second-section/A-first-lesson.md b/lessons/02-a-second-section/A-first-lesson.md
deleted file mode 100644
index 596e7df..0000000
--- a/lessons/02-a-second-section/A-first-lesson.md
+++ /dev/null
@@ -1,5 +0,0 @@
-- this
-- is
-- the
-- second
-- lesson
diff --git a/lessons/02-a-second-section/B-second-lesson.md b/lessons/02-a-second-section/B-second-lesson.md
deleted file mode 100644
index e46cc96..0000000
--- a/lessons/02-a-second-section/B-second-lesson.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-description: "An important second lesson"
----
-
-This is the second lesson
-
-```javascript
-function getGreeting() {
- return `oh hey there`;
-}
-
-console.log(getGreeting());
-```
diff --git a/lessons/02-a-second-section/meta.json b/lessons/02-a-second-section/meta.json
deleted file mode 100644
index 65498a9..0000000
--- a/lessons/02-a-second-section/meta.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "icon": "dumpster-fire"
-}
\ No newline at end of file
diff --git a/lessons/02-your-env/A-your-env.md b/lessons/02-your-env/A-your-env.md
new file mode 100644
index 0000000..b29414a
--- /dev/null
+++ b/lessons/02-your-env/A-your-env.md
@@ -0,0 +1,60 @@
+---
+title: "Intro into your env"
+description: "lets take a tour"
+---
+
+## The Environment
+So for me, when i say environment what i mean is everything surrounding the
+development process.
+
+
+
+How you install your favorite libraries
+
+How you interact with your operating system to get you where you want to be
+
+How you arrange your windows
+
+How you arrange your screens (desktops?)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## The most important starting place
+If you were given a brand new system how long does it take you set up? I would
+venture that most people spend a day getting ready to go followed by another
+couple days patching the holes.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lessons/02-your-env/B-ansible.md b/lessons/02-your-env/B-ansible.md
new file mode 100644
index 0000000..8382db2
--- /dev/null
+++ b/lessons/02-your-env/B-ansible.md
@@ -0,0 +1,594 @@
+---
+title: "Ansible"
+description: "ansible"
+---
+
+## Ansible
+Now a long running way I have been using to manage my dotfiles have been
+exclusively through ansible. There are several pluses to managing through
+ansible and there are some negatives
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Pros
+* there is tons of online documentation
+* its used more than just managing dotfiles
+* ansible vault allows for plain storage of ssh keys! which is really cool
+* you can also store a bunch of other cool stuff with ansible vault (think auth passcodes)
+
+## Cons
+* it can be terribly slow
+* it can be hard to make it work for certain tasks, such as installing neovim
+ plugins
+* tags can be great and super annoying
+* yaml sucks
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Basic Ansible
+lets create a simple ansible script to clone neovim from source and build it
+from a specific tagged version
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## What is ansible?
+From their github
+> Ansible is a radically simple IT automation system. It handles configuration management, application deployment, cloud provisioning, ad-hoc task execution, network automation, and multi-node orchestration. Ansible makes complex changes like zero-downtime rolling updates with load balancers easy. More information on the Ansible website.
+
+You are probably thinking... wait... aren't we talking about dotfiles and environments?
+
+
+
+
+Why yes we are!
+
+
+
+
+This is a tool designed for "servers" and if you squint your eyes you will
+realize that you are just working on a "server."
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Install ansible
+as all adventures start...
+
+```
+pip3 install ansible
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## The heart of ansible
+Typically when you are working with ansible you are using an inventory, which
+is a list of all servers you have proper access to, and a series of playbooks.
+The playbooks are where we specify the tasks we wish to perform on one or more
+nodes (machines). The playbook is the heart of ansible
+
+
+
+
+As a friend once said
+> ansible is the helicopter that drops godzilla
+>
+>
+>
+>
+>
+>
+>
+>
+>
+>
+>
+> ... godzilla being k8s
+
+
+
+
+Since we are operating on our own machine we wont need the inventory part, its
+just `localhost`
+
+
+
+
+Lets just jump right into the playbook side of ansible which is where all the
+work is done
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Your First Playbook
+Lets start off by creating a playbook that will use git to download the
+contents of neovim to a directory in a directory of our choosing
+
+* create a new directory, lets call it `mfansible`
+* create a file called `neovim.yml`
+* input the following
+
+```yml
+- name: My first playbook
+ hosts: localhost
+ tasks:
+```
+
+with this alone we can now execute ansible and see the effects
+
+```
+ansible-playbook neovim.yml
+```
+
+and you should see output that is similar to
+
+```
+➜ ansible-neovim-example git:(master) ✗ ansible-playbook neovim.yml
+[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
+
+PLAY [The Great Neovim editor] *****************************************************************************************************
+
+TASK [Gathering Facts] *************************************************************************************************************
+ok: [localhost]
+
+PLAY RECAP *************************************************************************************************************************
+localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Congrats!
+you have ran your first ansible script!
+
+Lets do some git
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Lets clone down neovim!
+When it comes to using ansible, one of my favorite features is the docs and how
+they are organized. it just makes it so simple to google and get the exact
+answer out you need. ChatGPT is nice to use, but can sometimes lead you into
+too much usage of odd features like scripting
+
+* Google ansible git clone
+* scroll the documentation and copy the one they suggest
+* perhaps combine a few to make this most efficient!
+
+
+
+
+But where do we put the code we find? Well... remember that empty `tasks` key?
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Expected Task Output
+
+
+```yaml
+- name: My first playbook
+ hosts: localhost
+ tasks:
+ - name: Git neovim
+ ansible.builtin.git:
+ repo: "https://github.com/neovim/neovim.git"
+ dest: "{{ lookup('ansible.builtin.env', 'HOME') }}/personal/neovim"
+ version: v0.10.2
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Become familiar with the build first
+there will be several libs that you may require to get this working so to do
+this correctly you will first want to build neovim by hand and keep track of
+the libraries that you need. There is likely a list of requirements in the
+[BUILD.md](https://github.com/neovim/neovim/blob/master/BUILD.md)
+
+### Making neovim requires packages
+Here are the packages i needed to install from apt to get neovim
+
+```bash
+sudo apt install cmake gettext lua5.1 liblua5.1-0-dev
+```
+
+### Lets get the libraries first
+Lets translate what I installed into an ansible command.
+
+* google how to ansible apt
+* copy the proper command
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Expected Code
+Your code should look something like this
+
+```yaml
+- name: My first playbook
+ hosts: localhost
+ tasks:
+ - name: Git neovim
+ ansible.builtin.git:
+ repo: "https://github.com/neovim/neovim.git"
+ dest: "{{ lookup('ansible.builtin.env', 'HOME') }}/personal/neovim"
+ version: v0.10.2
+
+ - name: Install helping libs
+ become: true
+ ansible.builtin.apt:
+ pkg:
+ - lua5.1
+ - liblua5.1-0-dev
+ - cmake
+ - gettext
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## OH NO! Crash!
+If you are using apt and have to use sudo you should see the following error.
+
+```
+<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: theprimeagen
+<127.0.0.1> EXEC /bin/sh -c 'echo ~theprimeagen && sleep 0'
+<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/theprimeagen/.ansible/tmp `"&& mkdir "` echo /home/theprimeagen/.ansible/tmp/ansible-tmp-1729644436.258113-1776352-80352927742333 `" && echo ansible-tmp-1729644436.258113-1776352-80352927742333="` echo /home/theprimeagen/.ansible/tmp/ansible-tmp-1729644436.258113-1776352-80352927742333 `" ) && sleep 0'
+Using module file /usr/lib/python3/dist-packages/ansible/modules/apt.py
+<127.0.0.1> PUT /home/theprimeagen/.ansible/tmp/ansible-local-1776140pp0cn_gm/tmp33hhis1k TO /home/theprimeagen/.ansible/tmp/ansible-tmp-1729644436.258113-1776352-80352927742333/AnsiballZ_apt.py
+<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /home/theprimeagen/.ansible/tmp/ansible-tmp-1729644436.258113-1776352-80352927742333/ /home/theprimeagen/.ansible/tmp/ansible-tmp-1729644436.258113-1776352-80352927742333/AnsiballZ_apt.py && sleep 0'
+<127.0.0.1> EXEC /bin/sh -c 'sudo -H -S -n -u root /bin/sh -c '"'"'echo BECOME-SUCCESS-rgqphadrxzwvmzhucbtnjvxefbemoqpt ; /usr/bin/python3 /home/theprimeagen/.ansible/tmp/ansible-tmp-1729644436.258113-1776352-80352927742333/AnsiballZ_apt.py'"'"' && sleep 0'
+<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /home/theprimeagen/.ansible/tmp/ansible-tmp-1729644436.258113-1776352-80352927742333/ > /dev/null 2>&1 && sleep 0'
+fatal: [localhost]: FAILED! => {
+ "changed": false,
+ "module_stderr": "sudo: a password is required\n",
+ "module_stdout": "",
+ "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
+ "rc": 1
+}
+```
+
+Well ansible does have the ability to become the sudo but it needs the creds to
+do it, you can type in those creds before installing by using the -K flag
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Now build!
+Now all we have to build neovim and then sudo make install! We do the same
+process
+
+* google make
+* copy the relevant instructions
+* implement the new tasks
+* ...
+* neovim (which is profit)!
+
+### To make neovim (from BUILD.md)
+The command to run to make neovim is the following:
+
+```bash
+cd neovim && make CMAKE_BUILD_TYPE=RelWithDebInfo
+```
+
+then to install it we need to execute
+
+```bash
+sudo make install
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Expected output
+```yaml
+- name: My first playbook
+ hosts: localhost
+ tasks:
+ - name: Git neovim
+ ansible.builtin.git:
+ repo: "https://github.com/neovim/neovim.git"
+ dest: "{{ lookup('ansible.builtin.env', 'HOME') }}/personal/neovim"
+ version: v0.9.4
+
+ - name: Install helping libs
+ become: true
+ ansible.builtin.apt:
+ pkg:
+ - lua5.1
+ - liblua5.1-0-dev
+ - cmake
+ - gettext
+
+ - name: neovim
+ make:
+ chdir: "{{ lookup('ansible.builtin.env', 'HOME') }}/personal/neovim"
+ params:
+ CMAKE_BUILD_TYPE: "RelWithDebInfo"
+
+ - name: neovim install
+ become: true
+ make:
+ target: install
+ chdir: "{{ lookup('ansible.builtin.env', 'HOME') }}/personal/neovim"
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## And that is ansible
+that is what it takes to create neovim ansible.
+
+
+
+
+### Why would i use this over a bash script
+A bash script is great when you can execute it on a machine, but ansible allows
+you to execute all these operations on a bunch of host machines at once, your
+machine, uniform syntax (yml). It also allows for some custom logic based on
+operating system so you could interchange out the fetching mechanism to make it
+machine independent
+
+
+
+
+Ansible can be real great. It "seems" easier to maintain than having a bunch
+of bash scripts for each operating system. It can also make automating your
+setup a bit easier.
+
+
+
+
+But for me... its a no at this point. I prefer a single script that i control
++ some basic convention. Convention over configuration is a mantra i support
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lessons/02-your-env/C-roll-your-own.md b/lessons/02-your-env/C-roll-your-own.md
new file mode 100644
index 0000000..04c0f12
--- /dev/null
+++ b/lessons/02-your-env/C-roll-your-own.md
@@ -0,0 +1,542 @@
+---
+title: "Reinvent the wheel"
+description: "its one of the best past times"
+---
+
+## Reinvent the wheel
+I love reinventing the wheel. There are many reasons why i like doing it too!
+
+
+
+
+### You will gain
+* a new appreciation of what it takes to create software
+* learn a bunch about the topic along the way
+* become a better engineer yourself, meaning you will now be able to guage
+ problems more accurately
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## My Current Bash Setup
+This is obviously subject to change. About once a year to every two years I
+try to rethink through everything I have done and see if its something i like
+or hate. That way I can continue to improve my system but I don't end up
+becoming a meme of the continually pursuit of perfection.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Lets set some goals
+* I want to be able to bootstrap any machine i will purchase in the future that
+ is ubuntu based.
+ * i am not going to be clever and try to do a multiOS style, though this
+ isn't hard its just tedious
+ * if i need a mac install script i am sure i can create a mac version
+* I want to be able to install all my favorite libraries
+* I want the repos that i actively maintained brought down
+* I want to be able to build neovim from source
+* I want all the tools i use available
+* I want to copy all my dotfiles over to my env. i like them separated.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## I just want it all
+I really just want to automate my system with the greatest automation language
+of all time...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+bash
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Rolling out own
+There are other versions of this exact same project that is someone elses
+version. I want to emphasize that I think the more you own of your system the
+better it will be because its exactly the way you want it. You have the power
+to fashion it the way you want!
+
+
+
+
+But i am not foolish, this is also a double edge sword where you have to
+maintain and improve your own system to make continue to make it great.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## The idea
+Create a script called `run` that will, based on some arguments passed in,
+will run 0 or more scripts. I want to make sure that scripts are easily
+organized so the scripts will be located in a subdirectory called `runs`
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## My version
+If you want to check out my final version of this product, check out my repo
+named [dev](https://github.com/theprimeagen/dev)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Argument parsing and script setup
+Now we need to write the ackshual run script. Lets start with first creating
+the dev environment. Meaning getting the libraries, projects, editor, etc etc
+that we want on our machine.
+
+*Perhaps a bit of white boarding could be useful here...*
+
+* create a project directory anywhere you deem fit
+* create a script called `run` within the directory you just created and make it executable (chmod +x run) within
+* open up your favorite text editor neovim (maybe something else...)
+
+
+
+
+### Start simple
+* code up something that allows us to know the current directory and take in 1
+argument for filtering of tasks
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Expected Code
+```bash
+#!/usr/bin/env bash
+
+script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
+echo "$script_dir"
+
+filter="$1"
+
+echo "Run: dir $script_dir -- filter \"$filter\""
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## But how do we run scripts?
+* we need to use our current script location to figure out all the available
+ scripts and run them one by one and if we have a mask/filter/grep then use
+ that to prevent any extra execution
+
+* coding time...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Expected Code
+
+```bash
+# ... previous section ...
+script_dir="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)"
+filter="$1"
+
+cd $script_dir
+scripts=$(find runs -maxdepth 1 -mindepth 1 -executable -type f)
+
+for script in $scripts; do
+ if echo "$script" | grep -qv "$filter"; then
+ echo "filtered: $filter -- $script"
+ continue
+ fi
+ ./$script
+done
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Quick Note
+why single bracket comparison ?
+
+```bash
+if [ ! -z "$myvar" ]; then ...
+```
+why double bracket comparison ?
+
+```bash
+if [[ $myvar == "" ]]; then ...
+```
+
+why no bracket comparison ?
+
+```bash
+if echo $myvar | grep -q "hello world"; then ...
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Back to the program
+We officially have our files being ran and we have filtering, and this is great.
+
+But what if we need to debug this bash script? We don't really have a way
+other than add a bunch of print statements and potentially run some side
+effects we were not expecting
+
+We need a `dry_run`, so lets write it now!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Expected Code
+Here is the full code up to this point
+
+```bash
+#!/usr/bin/env bash
+
+script_dir="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)"
+filter=""
+dry="0"
+
+cd $script_dir
+scripts=$(find runs -maxdepth 1 -mindepth 1 -executable -type f)
+
+while [[ $# > 0 ]]; do
+ if [[ "$1" == "--dry" ]]; then
+ dry="1"
+ else
+ filter="$1"
+ fi
+ shift
+done
+
+log() {
+ if [[ $dry == "1" ]]; then
+ echo "[DRY_RUN]: $@"
+ else
+ echo "$@"
+ fi
+}
+
+execute() {
+ log "execute: $@"
+ if [[ $dry == "1" ]]; then
+ return
+ fi
+
+ "$@"
+}
+
+log "run: filter=$filter"
+
+for script in $scripts; do
+ if echo "$script" | grep -qv "$filter"; then
+ log "filtered: $filter -- $script"
+ continue
+ fi
+ log "running script: $script"
+ execute ./$script
+done
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Boom!
+We now have a script that is easily extensible for setting up our environment
+
+* You can add as many scripts as you would like
+* You can filter which scripts get ran
+* You can easily edit those scripts to be exactly what you want
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Some cons
+* Bash sort of sucks..
+* Keeping things up date is easy to forget
+ * this is also why i always copy my environment. i never edit the env files
+ directly. A good habit for me
+* Making it OS independent is a bit of a pain in the ass
+ * i would argue its easier and up to as hard as ansible
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Other thoughts on dry runs
+You `export DRY_RUN` during the dry run checks and then run every script and
+let your scripts be the ones that tell you what it would be doing instead of
+doing it.
+
+I just find that amount of logic is nice on paper but a huge pain in practice
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lessons/02-your-env/D-neovim.md b/lessons/02-your-env/D-neovim.md
new file mode 100644
index 0000000..f1ffda2
--- /dev/null
+++ b/lessons/02-your-env/D-neovim.md
@@ -0,0 +1,91 @@
+---
+title: "Put it all together"
+description: "Life is but a curl away..."
+---
+
+## Lets install neovim
+With ansible we:
+* downloaded the neovim source
+* built from neovim source
+* installed neovim
+
+
+
+
+Lets build the same thing, but in the bash script now!
+
+gituah: git@github.com:neovim/neovim.git
+deps: cmake gettext lua5.1 liblua5.1-0-dev
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Executable Code
+```bash
+#!/usr/bin/env bash
+
+git clone git@github.com:neovim/neovim.git ~/personal/neovim
+cd ~/personal/neovim
+git fetch
+git checkout v0.9.2
+
+sudo apt install cmake gettext lua5.1 liblua5.1-0-dev
+make CMAKE_BUILD_TYPE=RelWithDebInfo
+sudo make install
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## And this is why I like bash
+Ansible is great and i used it for years, but in the end i am just going to use
+bash. I find it easier to maintain and i just find it more enjoyable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lessons/02-your-env/E-wait.md b/lessons/02-your-env/E-wait.md
new file mode 100644
index 0000000..7b08c27
--- /dev/null
+++ b/lessons/02-your-env/E-wait.md
@@ -0,0 +1,272 @@
+---
+title: "Wait A Second"
+description: "what about all the dot files?"
+---
+
+## We only have talked about getting the software up
+What about dotfiles...
+What about configuration...
+WHAT ABOUT MY CUSTOMIZATIONS
+
+
+
+
+For those unfamiliar with the term dotfiles, it simple means a script that is
+ran at the start of your program. A `.bashrc` / `.zshrc` / `.vimrc` are all
+examples of dotfiles that run before the program startup is complete. It is
+the place for you to register your custom functionality or to alter program
+behavior
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Well we already have everything we need
+We have everything we need to get started, we have our reliable environmental
+script to run, we just need one script that sets up our environment!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## The Env Idea
+* make a script that installs all the environment files.
+* make one or more directories to where you like to install files to
+
+
+
+
+### Lets do this!
+* whiteboard time!
+* code time!
+* lets start by getting the basics of the script ready
+ * dry run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Expected Code
+```bash
+#!/usr/bin/env bash
+
+script_dir="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)"
+dry="0"
+
+while [[ $# > 0 ]]; do
+ if [[ "$1" == "--dry" ]]; then
+ dry="1"
+ fi
+ shift
+done
+
+log() {
+ if [[ $dry == "1" ]]; then
+ echo "[DRY_RUN]: $@"
+ else
+ echo "$@"
+ fi
+}
+
+execute() {
+ log "execute: $@"
+ if [[ $dry == "1" ]]; then
+ return
+ fi
+
+ "$@"
+}
+
+log "--------- dev-env ---------"
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Copy time
+Lets create the copy function that will bring over every source directory to
+the target directory
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Expected code
+```bash
+cd $script_dir
+copy_dir() {
+ pushd $1
+ to=$2
+ dirs=$(find . -maxdepth 1 -mindepth 1 -type d)
+ for dir in $dirs; do
+ execute rm -rf $to/$dir
+ execute cp -r $dir $to/$dir
+ done
+ popd
+}
+
+copy_dir .config $XDG_CONFIG_HOME
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## And just like that
+We have ourselves a way to copy over directories for all of our programs... but
+what about one off scripts?
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Expected Code
+```bash
+copy_file() {
+ file=$1
+ to=$2
+ execute rm $to/$file
+ execute cp $file $to
+}
+
+copy_file .specialrc ~/
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## We make things bigger than they are
+this will solve about 99% of all dotfile management issues.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lessons/03-navigation/A-window.md b/lessons/03-navigation/A-window.md
new file mode 100644
index 0000000..388e109
--- /dev/null
+++ b/lessons/03-navigation/A-window.md
@@ -0,0 +1,192 @@
+---
+title: "Window Managers"
+description: "window managers"
+---
+
+## The most important aspect
+Is navigation.
+
+> You should never need your mouse or search with your eyes for your most common operations
+
+This is how i think of my navigation:
+
+1. 99.5% of things i do consistently, turn that into 1 to 2 buttons being
+ pressed
+1. 0.5% of things i do from time to time and i am ok using a mouse
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## The window manager
+One of the most powerful things you can use is a window manager because it
+takes care of one of the most annoying facets of computers. Placing windows
+
+
+If you are still placing windows manually, you are living in the stone age.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Window managers
+This will not be a large part of the course, but this will be the basis for how
+I approach everything from here on out.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## What is a window manager?
+This will really depend on the window manager you use.
+
+* pop os
+* i3
+* awesomewm
+* leftwm
+* yabai (mac)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## The strategy I employ
+So there are many strategies you can employ, but here is the way I got about
+using a window manager.
+
+1. focus
+2. one key to where i need
+
+
+
+
+Let me get out ol gimp to show you what what i mean
+* the complexity of mac desktops and navigation
+* one one key matters
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Opening programs
+Another thing that windows and mac users have pretty much for free is a nice
+search bar for opening programs. Apple's Spotlight pretty much gets you what
+you want asap.
+
+For linux, there is `rofi`, `dmenu`, and likely 100 more (its linux afterall)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## I don't give any recs
+Notice that i am not giving any recommendations here. I just don't think it
+matters. I don't see how you using AwsomeWM is going to make much of a
+difference with my workflow as using i3.
+
+Now if i used more features, such as more than one window at a time in desktop
+I may need to explore more and come up with "better" solutions. But at this
+point, for me it makes no difference.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lessons/03-navigation/B-tmux.md b/lessons/03-navigation/B-tmux.md
new file mode 100644
index 0000000..8b32ac4
--- /dev/null
+++ b/lessons/03-navigation/B-tmux.md
@@ -0,0 +1,723 @@
+---
+title: "Tmux"
+description: "tmux is a great way to navigate around the terminal"
+---
+
+## The Terminal Experience
+I have a list of things i want in my terminal to make it useful and it all is
+
+centered around navigation.
+
+### What I Want
+1. sessions that last even when i close my terminal
+1. multiple running sessions, and these sessions are based on directory
+1. "tabs" within a session
+1. navigate to any session by directory name "instantly"
+1. navigate to any session by directory with fuzzy find
+1. run scripts or whatever programs i want when navigating to a directory
+
+** TO GIMP **
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## I Choose Tmux
+I personally use tmux + ghostty, though i hear wezterm, another terminal
+emulator, you can emulate pretty much every way I use tmux. I have not used
+wezterm so i cannot speak much about it. Zellij has similar experience but more
+modern
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Quick Notes
+* About 3 years ago I did the first version of Dev productivity and some things
+ about my setup has changed, and parts have remained the same. After 3 years,
+ this is still my most useful script I have ever created. But i have added
+ some significant improvements to the script
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Installing TMUX
+| Platform | Install Command |
+|-----------------------------|-------------------------|
+| Arch Linux | `pacman -S tmux` |
+| Debian or Ubuntu | `apt install tmux` |
+| Fedora | `dnf install tmux` |
+| RHEL or CentOS | `yum install tmux` |
+| macOS (using Homebrew) | `brew install tmux` |
+| macOS (using MacPorts) | `port install tmux` |
+| openSUSE | `zypper install tmux` |
+
+### Base Config
+Here is the basic config that will make life easier. This will ensure that you
+have a similar experience to me
+
+```bash
+set -g default-terminal "tmux-256color"
+set -s escape-time 0
+set -g base-index 1
+
+# optional -- i like C-a not C-b (pure preference)
+unbind C-b
+set-option -g prefix C-a
+bind-key C-a send-prefix
+
+# = XDG_CONFIG_HOME/tmux/tmux.conf
+# = ~/.tmux.conf
+bind r source-file \; display-message "tmux.conf reloaded"
+```
+
+### Install it via our dev-env!
+We can even use our fancy new dev-env script to install it!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Lets navigate tmux
+Lets go through some basic commands about tmux so you can see how they work
+with just usage. I will show you the ones I use and some that I don't use
+
+* what is prefix key
+* creating window
+* detaching
+* attaching
+* showing all running sessions
+* killing pane / window / session
+* creating and navigating splits
+ * tmux is controlled by a config
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## A bit of customization
+I like to navigate my tmux panes like i navigate my vim windows
+
+lets try this out:
+
+```bash
+# Add to your tmux.conf file
+bind -r h select-pane -L
+bind -r j select-pane -D
+bind -r k select-pane -U
+bind -r l select-pane -R
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Based on my previous 5 points, only two have been met.
+> 1. sessions that last even when i close my terminal
+> 3. "tabs" within a session
+
+
+
+
+It turns out that `tmux` is also scriptable! And its quite fantastic
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## The Session API
+
+A `target` is a tuple of `[:|[.]]`
+
+```bash
+tmux new-session -s -n -d[etach]
+tmux list-sessions
+tmux attach-session -t
+tmux has-session -t # don't forget -t vs -t=
+tmux switch-client -t
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## The Window API
+
+```bash
+tmux new-window -n [-t session:window_index]
+tmux list-windows [-t session]
+tmux select-window -t session:[window_idx | window_name].[pane_idx]
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Other fun apis
+
+```bash
+tmux send-keys -t "text" [ctrl keys,...]
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Lets start with our first script
+From my original points, we still have 4 points left to address to create the
+"perfect" navigation system for the terminal
+
+### What I Want
+1. DONE :: sessions that last even when i close my terminal
+1. multiple running sessions, and these sessions are based on directory
+1. DONE :: "tabs" within a session
+1. navigate to any session by directory name "instantly"
+1. navigate to any session by directory with fuzzy find
+1. run scripts or whatever programs i want when navigating to a directory
+
+## Lets Address Point 6 First
+This is one of the easier points to address
+
+* opens and creates the configuration you want for a project
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Opener script
+
+```bash
+#!/usr/bin/env bash
+
+if [[ -x ./.ready-tmux ]]; then
+ ./.ready-tmux
+elif [[ -x ~/.ready-tmux ]]; then
+ ~/.ready-tmux
+fi
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Thats pretty cool?
+That was pretty awesome that we can create all the windows / splits we want
+with a simple script (don't worry, it'll get a lot better)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Progress
+We have checked off another component of what I consider a great terminal
+experience
+
+> 6. run scripts or whatever programs i want when navigating to a directory
+
+But we still have a few left
+
+> 2. multiple running sessions, and these sessions are based on directory
+> 4. navigate to any session by directory name "instantly"
+> 5. navigate to any session by directory with fuzzy find
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Detour time
+FZF is an incredible tool for fuzzy finding. Its not just for finding
+directories. You can fuzzy find on anything you pass in and is often used
+within text editors.
+
+### I will add fzf to my scripts
+
+`dev-env/runs/libs`
+```bash
+# ... other libs i install ...
+
+git clone git@github.com:junegunn/fzf.git $HOME/personal/fzf
+$HOME/personal/fzf/install
+```
+
+`dev-env/env/.zsh_profile`
+```bash
+## All that sweet sweet fzf
+[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh
+```
+
+### Execute
+Make sure i only run my libs script
+`run --dry libs`
+
+Run my lib script
+`run libs`
+
+Copy all of my files over
+`dev-env`
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Test run
+try pressing `C-r` (Control + r) and it should bring up a beautiful fuzzy find
+comparatively to your standard `C-r` from the terminal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Playing with FZF
+
+input
+```bash
+➜ dev-prod-2 git:(main) ✗ echo "1\n2\n3" | fzf
+```
+
+output
+```bash
+ 3
+ 2
+▌ 1
+ 3/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+>
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Lets solve the last problems
+> 2. multiple running sessions, and these sessions are based on directory
+> 4. navigate to any session by directory name "instantly"
+> 5. navigate to any session by directory with fuzzy find
+
+### Some notes
+* We don't want to search _every_ directory on the file system, we want to have
+some sort of subset.
+
+* We want to navigate based on the results of FZF
+
+### CODE TIME!!
+Lets start this MF script (MF = Mother FZF):
+* get a selected directory from fzf.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Expected Code
+```bash
+#!/usr/bin/env bash
+
+selected=$(find ~/personal -mindepth 1 -maxdepth 1 -type d | fzf)
+echo "selected!! $selected"
+```
+
+### Ok, lets do some great things
+* is there a running session given name
+ * `:,.` are not allowed as session name
+ * ` ` we should also remove spaces... but if you use a space in your directory name i dislike you
+ * there are other non allowed characters, but we will not worry about them
+* if there is, navigate to that session
+* if there is not, create that session and navigate to it
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Expected Code
+
+```bash
+#!/usr/bin/env bash
+
+selected=$(find ~/personal ~/ ~/.config -maxdepth 1 -mindepth 1 -type d | fzf)
+if [[ -z "$selected" ]]; then
+ exit 0
+fi
+selected_name=$(basename "$selected" | tr ",.: " "____")
+
+if tmux has-session -t=$selected_name 2> /dev/null; then
+ tmux switch-client -t=$selected_name
+ exit 0
+fi
+
+if [[ -z "$TMUX" ]]; then
+ tmux new-session -s $selected_name -c $selected
+ exit 0
+fi
+
+tmux new-session -ds $selected_name -c $selected
+tmux switch-client -t $selected_name
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Combine our two scripts
+It would be nice if we could combine our two scripts...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Next Expected Script
+```bash
+#!/usr/bin/env bash
+
+selected=$(find ~/personal ~/ ~/.config -maxdepth 1 -mindepth 1 -type d | fzf)
+if [[ -z "$selected" ]]; then
+ exit 0
+fi
+selected_name=$(basename "$selected" | tr ",.: " "____")
+
+if tmux has-session -t=$selected_name 2> /dev/null; then
+ tmux switch-client -t=$selected_name
+ exit 0
+fi
+
+if [[ -z "$TMUX" ]]; then
+ tmux new-session -s $selected_name -c $selected
+else
+ tmux new-session -ds $selected_name -c $selected
+ tmux switch-client -t $selected_name
+fi
+tmux send-keys -t $selected_name "ready-tmux"
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## How do i execute this?
+* we copy it to a $PATH location
+* we can create a tmux shortcut to execute it
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lessons/03-thoughts-on-js-and-css/A-css.md b/lessons/03-thoughts-on-js-and-css/A-css.md
deleted file mode 100644
index 1667ca5..0000000
--- a/lessons/03-thoughts-on-js-and-css/A-css.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "CSS"
-description: "CSS is for styling"
----
-
-CSS is important
diff --git a/lessons/03-thoughts-on-js-and-css/B-javascript.md b/lessons/03-thoughts-on-js-and-css/B-javascript.md
deleted file mode 100644
index d847fa8..0000000
--- a/lessons/03-thoughts-on-js-and-css/B-javascript.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "JavaScript"
----
-
-Seems important, right?
diff --git a/lessons/03-thoughts-on-js-and-css/C-npm.md b/lessons/03-thoughts-on-js-and-css/C-npm.md
deleted file mode 100644
index 4f884c2..0000000
--- a/lessons/03-thoughts-on-js-and-css/C-npm.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "npm"
-description: "npm doesn't stand for node package manager"
----
-
-npm doesn't stand for node package manager
diff --git a/lessons/03-thoughts-on-js-and-css/meta.json b/lessons/03-thoughts-on-js-and-css/meta.json
deleted file mode 100644
index 9c91e6b..0000000
--- a/lessons/03-thoughts-on-js-and-css/meta.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "title": "Thoughts on JS and CSS",
- "icon": "file-code"
-}
\ No newline at end of file
diff --git a/lessons/04-tools/A-intro.md b/lessons/04-tools/A-intro.md
new file mode 100644
index 0000000..7317c33
--- /dev/null
+++ b/lessons/04-tools/A-intro.md
@@ -0,0 +1,64 @@
+---
+title: "Intro"
+description: "The best of the best"
+---
+
+## Supercharging your dev life
+One of the best ways to dramatically increase the speed of what you are doing
+is learning the posix ways and some of the tools out there to massively improve
+your life
+
+
+
+
+I cannot tell you how many times in my earlier life i wrote a program that one
+small line of bash could have taken care of for me. Just knowing your tools is
+a massive advantage in developer life.
+
+
+
+
+Another reality of dev'ing is that for a while a single tool will be so useful,
+then you wont use it again for months. This has been my relationship with jq.
+Its ok, you will forget the practical part, but you wont forget what you can do
+as you learn these tools.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Note for FZF
+We already installed used it, so... its on the list of tools you should know
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lessons/04-tools/B-jq.md b/lessons/04-tools/B-jq.md
new file mode 100644
index 0000000..ff65117
--- /dev/null
+++ b/lessons/04-tools/B-jq.md
@@ -0,0 +1,239 @@
+---
+title: "Tools"
+description: "jq a hidden treasure"
+---
+
+## JQ
+JQ, the hidden treasure in the family of CLI tools. This one has personaly
+saved me so much time its hard to qualify just how important it is
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Lets create a file with the following content
+```json
+{"type": "foo", "values": [1, 2, 3, 4, 5]}
+{"type": "foo", "values": [69, 420, 42, 69420]}
+{"type": "bar", "values": {"a": 42, "b": 69}}
+{"type": "bar", "values": {"a": 1337, "b": 420}}
+{"type": "bar", "values": {"a": 111, "b": 222}}
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## prettify logs
+
+```bash
+cat out | jq # jq '' out
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## compact json
+
+```bash
+cat out | jq | jq -c
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## check this out
+
+```json
+{
+ "type": "foo",
+ "values": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5
+ ]
+}
+{
+ "type": "foo",
+ "values": [
+ 69,
+ 420,
+ 42,
+ 69420
+ ]
+}
+{
+ "type": "bar",
+ "values": {
+ "a": 42,
+ "b": 69
+ }
+}
+{
+ "type": "bar",
+ "values": {
+ "a": 1337,
+ "b": 420
+ }
+}
+{
+ "type": "bar",
+ "values": {
+ "a": 111,
+ "b": 222
+ }
+}
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## lets look at the data
+Lets sum _ALL_ the foo's `values` arrays PER struct
+
+```json
+{"type": "foo", "values": [1, 2, 3, 4, 5]}
+{"type": "foo", "values": [69, 420, 42, 69420]}
+{"type": "bar", "values": {"a": 42, "b": 69}}
+{"type": "bar", "values": {"a": 1337, "b": 420}}
+{"type": "bar", "values": {"a": 111, "b": 222}}
+```
+
+```bash
+➜ dev-prod-2 git:(main) ✗ cat out | jq 'select(.type == "foo") | .values | add'
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## lets do it again
+Lets sum _ALL_ the foo's `values` arrays and add it as a key to `type: foo` `valueSum`
+
+```json
+{"type": "foo", "values": [1, 2, 3, 4, 5]}
+{"type": "foo", "values": [69, 420, 42, 69420]}
+{"type": "bar", "values": {"a": 42, "b": 69}}
+{"type": "bar", "values": {"a": 1337, "b": 420}}
+{"type": "bar", "values": {"a": 111, "b": 222}}
+```
+
+```bash
+➜ dev-prod-2 git:(main) ✗ cat out | jq 'select(.type == "foo") | .valueSet = (.values | add)'
+```
+
+
+
+
+## We can filter out the `valueSet` now
+```bash
+➜ dev-prod-2 git:(main) ✗ cat out | jq 'select(.type == "foo") | .valueSet = (.values | add) | select(.valueSet > 20)'
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lessons/04-tools/C-unix.md b/lessons/04-tools/C-unix.md
new file mode 100644
index 0000000..3f2067d
--- /dev/null
+++ b/lessons/04-tools/C-unix.md
@@ -0,0 +1,183 @@
+---
+title: "Unix Tools!"
+description: "unix tools"
+---
+
+## Unix Tools
+The unix set is super useful to know and we can do quite a bit of useful
+transformation with them.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## lets transform out! (the json file)
+`sed` is a fun tool
+
+* lets replace `foo` with `bar`
+* lets replace `foo` or `bar` with `foo,foo` or `bar,bar`
+
+```bash
+➜ dev-prod-2 git:(main) cat out | sed 's/: "\(.*\)",/: "\1,\1",/'
+```
+
+### Expected
+```bash
+{"type": "foo,foo", "values": [1, 2, 3, 4, 5]}
+{"type": "foo,foo", "values": [69, 420, 42, 69420]}
+{"type": "bar,bar", "values": {"a": 42, "b": 69}}
+{"type": "bar,bar", "values": {"a": 1337, "b": 420}}
+{"type": "bar,bar", "values": {"a": 111, "b": 222}}
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## find
+list out files and do stuff
+
+```bash
+➜ dev-prod-2 git:(main) ✗ find . -maxdepth 1 -mindepth 1 -type f -exec grep -Hn "foo" {} \;
+./out:1:{"type": "foo", "values": [1, 2, 3, 4, 5]}
+./out:2:{"type": "foo", "values": [69, 420, 42, 69420]}
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## xargs
+a great tool
+
+```bash
+➜ dev-prod-2 git:(main) ✗ echo "1\n2\n3" | xargs -I {} curl https://{}.com
+curl: (6) Could not resolve host: 1.com
+curl: (6) Could not resolve host: 2.com
+curl: (6) Could not resolve host: 3.com
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## parallel
+such a great tool
+
+lets write a file with the entries of 1 through 9, per line
+```
+1
+2
+3
+4
+5
+6
+7
+8
+9
+```
+
+now lets use parallel to control how fast it requests
+
+```bash
+➜ dev-prod-2 git:(main) ✗ cat count | parallel -j 5 "curl https://{}.com"
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Just a touch of awk
+I don't know a lot of awk and you can do quite a bit, but the little i do know is really good
+
+```bash
+➜ dev-prod-2 git:(main) ✗ ps aux | grep vim | awk '{ sum += $2 } END { print sum }'
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lessons/04-tools/D-neovim.md b/lessons/04-tools/D-neovim.md
new file mode 100644
index 0000000..85af71a
--- /dev/null
+++ b/lessons/04-tools/D-neovim.md
@@ -0,0 +1,273 @@
+---
+title: "Tools"
+description: "your most used tool is the editor"
+---
+
+## Lets start with your editor
+Now i am going to show you around neovim, not because you are going to use
+neovim, but its good understand just how hackable it is and perhaps you will be
+willing to try it
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Creating your own neovim experience
+I'll just give you a brief look at neovim and what you can do. This isn't
+really a "follow" along section, but if you already have neovim setup, you
+could.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## One more note about vim
+If you are getting a bit vim curious, seeing people fly around, its totally
+normal. But i do want to warn you about 2 things.
+
+1. you live in a world where you have really different mentality. This isn't
+ the era that vi or vim was created. So many modern luxuries that its hard
+ to connect at first with Vim. So the best thing you can do at first is to
+ learn vim motions. Once you are sufficiently amazing at vim motions, then move
+ on to using vim. And of course, i recommend neovim
+
+2. When you first use vim, there is no filetree on the left, menu at the top,
+ just text on the screen. This will make it hard to even read code because
+ of how unfamiliar and hostile the environment seems. Don't worry, that
+ feeling will go away.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Lets go over some of the motions
+Perhaps to give you a taste, lets go over some of the motions and why its
+amazing.
+
+We can also go over some of the awesome remaps that i have dev'd / been given
+over the last few years.
+
+* motions
+* qfix
+* harpoon
+* navigation
+* macros
+* commands
+* help
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## But why neovim?
+We get the best of both worlds, a modern IDE and vim motions. Why would I ever
+use neovim?
+
+* defense for neovim
+* the bonus of using neovim that isn't quite the same with other editors
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Lets play with the neovim api
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Expected Code
+```lua
+local function read_file_with_system(filename)
+ local pipe = vim.system({"cat", filename})
+ local content = pipe:wait().stdout
+ local lines = vim.split(content, "\n", { trimempty = true })
+ return lines
+end
+
+local api = vim.api
+local buf = api.nvim_create_buf(false, true)
+local win = api.nvim_open_win(buf, false, {
+ relative="editor",
+ width=80,
+ height=24,
+ row=0,
+ col=0,
+})
+api.nvim_buf_set_lines(buf, 0, -1, false, read_file_with_system("./package.json"))
+
+vim.defer_fn(function()
+ api.nvim_win_close(win, true)
+end, 5000)
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## There is so much more
+that was just a taste and there is so much more. I highly recommend playing
+around with the apis and making anything that you want.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## A quick note about AI
+One really nice thing about neovim is that the api is so well documented and
+the surface area so well defined that you can often one shot exactly what you
+need with neovim and chatgpt.
+
+this isn't always the case, it still makes up stuff ~5% of the time, but its
+close.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## VimBeGood
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lessons/05-terminal/A-intro.md b/lessons/05-terminal/A-intro.md
new file mode 100644
index 0000000..7d549c1
--- /dev/null
+++ b/lessons/05-terminal/A-intro.md
@@ -0,0 +1,55 @@
+---
+title: "Terminally Retired"
+description: "this is my favorite place to be"
+---
+
+## This may get offensive
+I don't really care what terminal you use. I use Ghostty, its fast, and its
+created by someone I respect. That is it. Its really that simple.
+
+* I get to chose my own colorscheme easily with ghostty
+* I move on because all my customizations are at a different level
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Why Not?
+Alacritty - I was using it, now i am not
+Kitty - Provides more terminal experiences closer to tmux, but the owner is exceptionally unpleasant, so i wont use it.
+Ghostty - Provides everything Alactritty does but its by Mitchell!
+Xterm-256color - I used this for so long. The only reason i upgraded to a gpu accellerated term was so i could run ascii doom in 30 fps at "high resolution."
+Wezterm - I heard this one can make it so i don't have to use tmux anymore. Thats pretty neet. Maybe one day i'll give it a try
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lessons/06-outro/A-outro.md b/lessons/06-outro/A-outro.md
new file mode 100644
index 0000000..b8e645d
--- /dev/null
+++ b/lessons/06-outro/A-outro.md
@@ -0,0 +1,50 @@
+---
+title: "Outro"
+description: "goodbye"
+---
+
+## And this is it
+Its the joy of making a better experience that helps keep me engaged as a dev.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Important note
+The most important thing about this course is not to do what I do, but to do
+what _you_ want to do. Now I emphasized the most important tools you can get
+familiar with and their variations. Learn, enjoy, and figure out what you
+want.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+