Tutorial
-
The Human's Guide to the Command Line: Your First CLI App
This is Part 2 of The Human’s Guide to the Command Line. If you missed Part 1, go check that out first — we got Homebrew and Ghostty set up, which you’ll need for everything here.
Now we’re going to do something that feels like a big leap: we’re going to write a real command-line application. A small one, but a real one. Before we get there, though, we need two things — a programming language and a code editor.
Picking a Language
You can write CLI apps in a lot of languages. JavaScript, Go, Rust — they all work. But if you’re new to programming, I think Python is the right starting point. It reads almost like English, it’s everywhere, and you won’t spend your first hour fighting a compiler.
Python is what we’ll use for this series. That said, Python is notoriously tricky to set up locally; there are version managers, virtual environments, and a whole ecosystem of packaging tools that can make your head spin.
First things first, we need a code editor (an IDE).
A Code Editor: Zed
Before we write any code, you need somewhere to write it. We’re going to install Zed — it’s fast, clean, and won’t overwhelm you with buttons.
brew install --cask zedOpen Zed from your Applications folder once it finishes.
Install the
zedCommandHere’s the move that ties everything together. Open Zed’s command palette with Cmd + Shift + P, type
cli install, and hit Enter.Now you can open any folder in Zed directly from Ghostty:
zed . # open the current folder zed note.py # open a specific fileThat
.means “right here” — you’ll see it everywhere in the terminal and it always means the same thing: the folder you’re currently in.Set Up Your Project
Time to create a home for your code. Back in Ghostty:
mkdir ~/code mkdir ~/code/note cd ~/code/noteThree commands. You just created a
codefolder in your home directory, created anotefolder inside it, and stepped into it. Now open it in Zed:zed .Zed opens with your empty project folder in the sidebar on the left. This is where we’ll create our script.
Building a Note Taker
We’re going to build a tiny app called
note. It does three things: add a note, list your notes, and clear them all. That’s it. No database, no accounts, no cloud. Just you and a JSON file.Create your script in Zed’s sidebar by clicking the New File icon, name it
note.py, and paste in the code from the next section.import argparse import json import sys from datetime import datetime from pathlib import Path # Where your notes live — ~/notes.json NOTES_FILE = Path.home() / "notes.json" def load_notes(): if not NOTES_FILE.exists(): return [] with open(NOTES_FILE) as f: return json.load(f) def save_notes(notes): with open(NOTES_FILE, "w") as f: json.dump(notes, f, indent=2) def cmd_add(args): notes = load_notes() note = { "text": args.text, "added": datetime.now().strftime("%Y-%m-%d %H:%M"), } notes.append(note) save_notes(notes) print(f"Added: {args.text}") def cmd_list(args): notes = load_notes() if not notes: print('No notes yet. Add one with: note add "your note"') return for i, note in enumerate(notes, start=1): print(f"{i}. {note['text']} ({note['added']})") def cmd_clear(args): answer = input("Delete all notes? This can't be undone. (y/n): ") if answer.lower() == "y": save_notes([]) print("All notes cleared.") else: print("Cancelled.") def main(): parser = argparse.ArgumentParser( prog="note", description="A simple command-line note taker.", ) subparsers = parser.add_subparsers(dest="command") # note add "some text" add_parser = subparsers.add_parser("add", help="Add a new note") add_parser.add_argument("text", help="The note to save") # note list subparsers.add_parser("list", help="Show all notes") # note clear subparsers.add_parser("clear", help="Delete all notes") args = parser.parse_args() if args.command == "add": cmd_add(args) elif args.command == "list": cmd_list(args) elif args.command == "clear": cmd_clear(args) else: parser.print_help() if __name__ == "__main__": main()Part 3: Python Without the Mess (uv)
Your Mac already has Python on it, but don’t use it. That version belongs to macOS which it uses internally, and if you start installing things into it you can cause yourself real headaches. We’re going to use our own Python that’s completely separate.
The tool for this is uv. It manages Python for you and keeps everything isolated so you never touch the system version.
brew install uvThat’s the whole install. Verify it worked:
uv --versionYou should see a version number printed back. If you do, you’re good.
Create Your Project
Inside your
~/code/notefolder, run:uv initThis sets up a proper Python project in the current folder. You’ll see a few new files appear in Zed’s sidebar, but don’t worry. If you see a
hello.py, which uv creates as a starter file, you can delete it.Running Your Script
Once you have code in
note.py, run it like this:uv run note.py add "call the dentist" uv run note.py list uv run note.py clearuv runhandles everything — it picks the right Python version, keeps it sandboxed to this project, and runs your script. You never typepython3directly, you never activate a virtual environment, you never install packages globally. It just works.Try it now:
uv run note.py listIf you see
No notes yet. Add one with: note add "your note"but otherwise, everything should be working.
Try this: Once your script is running, try
uv run note.py --help. You’ll get a clean description of every command, automatically. That’s one of the thingsargparsegives you for free./ Programming / Python / Tutorial / Command-line
-
The Human's Guide to the Command Line (macOS Edition)
If you’ve ever stared at a terminal window and felt like you were looking at the cockpit of an airplane, this post is for you. The command line doesn’t have to be scary, and I’m going to walk you through setting up a genuinely great terminal experience on your Mac, from scratch.
This is Part 1 of a Series. I will update the links here as I publish the other articles.
The Mental Model
Before we type anything, here’s the thing you need to understand: the terminal is just a text-based version of Finder.
When you see a folder in Finder, you double-click to open it. In the terminal, you type
cd(change directory) to enter it. You can run applications from Finder, and you can run applications from the terminal. It’s just a different way to do things you already understand.Once that clicks, everything else falls into place.
Part 1: The Foundation (Homebrew)
On a Mac, you install apps from the App Store. On the command line, we use Homebrew — it’s basically the App Store for the terminal. It’s a package manager that makes installing tools painless.
Let’s start by opening the terminal. Hit Command + Space, type “Terminal”, and hit Enter. Then paste this:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"It’ll ask for your Mac password. When you type it, nothing will appear on the screen. This is normal, it’s a security feature, not a bug. Just type your password and hit Enter.
Homebrew needs admin access because it creates system-level folders (usually
/opt/homebrew) and changes their ownership from the system account to your user account.Once it finishes, verify it’s working:
which brewIf that doesn’t return a path, run these two lines to add Homebrew to your shell:
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile eval "$(/opt/homebrew/bin/brew shellenv)"Part 2: A Better Terminal (Ghostty)
Now that we have Homebrew, the first thing we’re going to install is a better terminal. The built-in Terminal app works, but Ghostty is faster, more configurable, and just nicer to use.
brew install --cask ghosttyOnce it finishes, find Ghostty in your Applications folder and open it. You can close the old Terminal app forever, congratulations, you’ve graduated.
Part 3: Making It Beautiful (Nerd Fonts & Starship)
Standard fonts don’t have icons for folders, git branches, or cloud status. We need a Nerd Font so the terminal can speak in pictures.
Install the Font
brew install --cask font-fira-code-nerd-fontThen go to Ghostty’s settings (
Cmd + ,), find the Text section, and set your font toFiraCode Nerd Font.Install Starship
Starship is the paint job that turns a boring
$prompt into something colorful and actually helpful. It shows you what folder you’re in, what git branch you’re on, and more…brew install starshipWhile we’re at it, let’s install two plugins that make typing in the terminal way more pleasant. One whispers suggestions based on your command history, and the other color-codes your commands so you can spot typos before you hit Enter.
brew install zsh-autosuggestions zsh-syntax-highlightingWire It All Up
We need to tell your Mac to turn these features on every time you open a terminal. Copy and paste this entire block into Ghostty:
# Add Starship grep -qq 'starship init zsh' ~/.zshrc || echo 'eval "$(starship init zsh)"' >> ~/.zshrc # Add Auto-suggestions grep -qq 'zsh-autosuggestions.zsh' ~/.zshrc || echo "source $(brew --prefix)/share/zsh-autosuggestions/zsh-autosuggestions.zsh" >> ~/.zshrc # Add Syntax Highlighting grep -qq 'zsh-syntax-highlighting.zsh' ~/.zshrc || echo "source $(brew --prefix)/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" >> ~/.zshrc # Refresh your terminal source ~/.zshrcEach line checks if the setting already exists before adding it, so it’s safe to run more than once. When it finishes, your prompt should look completely different. Welcome to your CLI future.
Part 4: Basic Survival Commands
Now that your terminal looks proper, here’s how you actually move around.
Command Human Translation pwd“Where am I right now?” ls“Show me everything in this folder.” cd [folder]“Go inside this folder.” cd ..“Go back one folder.” clear“Wipe the screen and start fresh.” touch [file.txt]“Create a new blank file.” That’s about 90% of what you need to navigate around.
Two Golden Rules
1. Tab is your best friend. Type
cd Docand hit Tab — the terminal will finish the wordDocumentsfor you. This works for files, folders, and even commands. If there are multiple matches, hit Tab twice to see all the options.2. Ctrl + C is the panic button. If the terminal is doing something you didn’t expect, or a command is running and won’t stop, hold Ctrl and press C. It’s the emergency brake, and it’s always there for you.
A good next step: try navigating to your Desktop using only
cdandls. Find a file there, maybe create one withtouch, and then look at it withls. Once you can do that comfortably, you’ve officially mastered the basics./ Programming / Macos / Tutorial / Command-line