on this page

There’s a moment in every tutorial where the friendly screenshots stop and someone says “now just run this in your terminal,” and a black window opens, and your stomach drops. No buttons. No menus. Just a blinking cursor that looks like it’s waiting for you to type the one wrong thing that deletes your laptop.

Here’s the secret nobody tells you up front: you do not need to learn the terminal. You need to learn about twelve commands. The rest you look up when you need it, same as everyone else, forever. This guide gets you to the point where that black window is a tool you reach for, not a trap you tiptoe around.

What the terminal even is

The terminal is a text way to tell your computer to do things. That’s the whole idea. Everything you do by clicking (open a folder, make a new file, move it somewhere, throw it in the trash) you can also do by typing a short command. The mouse is friendlier for browsing. The terminal is faster for the stuff you repeat fifty times a day, and it’s the only way to drive most developer tools.

A bit of vocabulary, because three words get used interchangeably and it’s confusing:

  • The terminal is the window. It’s the app that shows the text and takes your keystrokes.
  • The shell is the program running inside that window that actually reads your commands and runs them. Common ones are Bash, Zsh, and PowerShell. When people say “open a terminal,” they mean “open a window with a shell in it,” and nobody distinguishes because it doesn’t matter day to day.
  • The prompt is the bit of text sitting there before your cursor, waiting. It usually shows something useful, like your username and the folder you’re currently in, then ends with a $ or > symbol. When you see the prompt, the shell is ready for a command. When you don’t, something’s still running.

A prompt might look like this:

carson@laptop ~/projects/my-app $

That’s telling you who you are, the machine you’re on, and where you are (~/projects/my-app). The $ means “go ahead.” You type a command after it and press enter to run it. That’s the entire interaction model: type, enter, read what comes back, type the next thing.

Where am I, and what’s here

Before you can move things around, you need to answer two questions: where am I standing, and what’s around me.

Every terminal session has a current working directory: the folder the shell is “in” right now. Commands run relative to it. When you say “list the files,” it lists the files here, in your current directory, not some other random place.

pwd prints the current working directory (“print working directory”). When you’re lost, this is the first thing you run.

pwd
# /Users/carson/projects/my-app

ls lists the files and folders in the current directory (“list”). This is your “what’s here” command, and you’ll run it constantly.

ls
# README.md  package.json  src  node_modules

By default ls hides files whose names start with a dot, called dotfiles, because they’re usually config the tools care about and you don’t want cluttering the view. Things like .env, .gitignore, and .git. To see them, add -a (“all”):

ls -a
# .  ..  .env  .git  .gitignore  README.md  package.json  src

For more detail (sizes, dates, permissions, one item per line), use -l (“long”):

ls -l
# -rw-r--r--  1 carson  staff   1124 Jun  5 09:14 README.md
# drwxr-xr-x  8 carson  staff    256 Jun  5 09:02 src

You don’t need to decode every column yet. The useful part early on: a line starting with d is a directory, one starting with - is a regular file. You can stack flags too, so ls -la shows everything in long form.

Moving around

cd changes which directory you’re in (“change directory”). This is how you walk through your project.

cd src
# now your current directory is .../my-app/src

A few cd moves are worth memorizing because you’ll use them hourly:

  • cd .. goes up one level, to the parent folder. Two dots means “the folder above this one.”
  • cd ~ goes home, to your user folder (/Users/you on a Mac, C:\Users\you on Windows). The ~ (tilde) is shorthand for home anywhere you use it.
  • cd - goes back to the last directory you were in, like the back button in a browser. Great for bouncing between two folders.
  • cd with nothing after it also takes you home, which is a handy “get me out of here” reset.

If you cd somewhere and lose track, run pwd. No shame in it. Experienced developers run pwd and ls reflexively, the way you glance at a road sign without thinking about it.

Making, copying, moving, deleting

Now the verbs that actually change things.

mkdir makes a new directory (“make directory”).

mkdir components
# creates a folder called components in the current directory

If you want a nested path and the in-between folders don’t exist yet, plain mkdir complains. Adding -p tells it to create every missing parent along the way (“p” for parents), no complaints:

mkdir -p src/components/buttons
# creates src, then components, then buttons, whatever was missing

touch creates an empty file (or, if the file already exists, just nudges its “last modified” timestamp, which is where the name comes from). It’s the quickest way to make a new empty file before you open it in your editor:

touch src/components/Button.tsx
# now an empty Button.tsx exists, ready to edit

cp copies a file (“copy”). You give it the thing to copy, then where it goes:

cp .env.example .env
# copies .env.example to a new file named .env, original untouched

mv moves a file, and moving a file to a new name in the same folder is how you rename things (“move”). There’s no separate rename command. Renaming is just moving from the old name to the new one.

mv old-name.js new-name.js
# renames old-name.js to new-name.js

mv Button.tsx src/components/
# moves Button.tsx into the src/components folder, name unchanged

rm removes a file (“remove”). Here’s the part to read slowly: there is no recycle bin. A file you rm is gone, not in the trash, gone. The terminal assumes you meant it.

rm notes.txt
# notes.txt no longer exists, and it is not coming back

By itself, rm won’t delete a folder. To remove a directory and everything inside it, you add -r (“recursive,” meaning “go into it and everything under it”):

rm -r old-feature/
# deletes the folder old-feature and all its contents

And then there’s rm -rf, which combines recursive with -f (“force,” meaning “don’t ask me to confirm anything, just do it”). It is the most genuinely dangerous command a beginner runs, because it deletes an entire folder tree silently and instantly. It has its uses, but it has earned its scary reputation, and we’ll come back to it in the traps section below.

The core commands, in one place

Here’s the dozen worth knowing, with the one flag you’ll reach for most. Keep this nearby for a week and it’ll stick.

CommandWhat it doesCommon flag
pwdPrints your current directory(none used much)
lsLists files in the current directory-a show hidden dotfiles
cdChanges directorycd .. up, cd ~ home
mkdirMakes a new directory-p create nested parents
touchCreates an empty file(none used much)
cpCopies a file-r copy a whole folder
mvMoves or renames a file(none used much)
rmDeletes a file-r delete a folder (careful)
catPrints a file’s contents(none used much)
clearClears the terminal screen(none used much)
code .Opens the current folder in VS Codethe . means “here”
--helpShows how a command worksappend to any command

That code . line is worth a second look: once you have VS Code

Heads up. You're leaving raindev.fyi

This link heads to code.visualstudio.com, an external site we don't control. Cool to keep going?

Continue
installed, typing code . opens your whole current folder as a project in the editor. The single dot means “the current directory,” and you’ll use that dot in a lot of commands.

Paths: relative versus absolute

This trips up nearly everyone, so it’s worth slowing down. A path is just the address of a file or folder. There are two kinds, and mixing them up is behind a huge share of “but it works on my machine” confusion.

A relative path is relative to where you currently are. It describes the route from your current directory to the target. These are the ones with . and .. in them:

  • ./src means “the src folder right here in my current directory.” The ./ is “starting from here.”
  • ../ means “the folder one level up.” So ../package.json is “the package.json in my parent folder.”
  • src/components/Button.tsx (no leading slash) is also relative: start here, go into src, then components.

Relative paths are short and convenient, but their meaning depends entirely on your current working directory. Run the same relative path from a different folder and it points somewhere else, or nowhere.

An absolute path is the full address from the root of the filesystem, no matter where you’re standing. It always means the same place:

# macOS / Linux absolute path (starts at the root /)
/Users/carson/projects/my-app/src/index.ts

# Windows absolute path (starts at a drive letter)
C:\Users\carson\projects\my-app\src\index.ts

The giveaway: on macOS and Linux an absolute path starts with a /. On Windows it starts with a drive letter like C:\. If a path starts with ., .., or a plain name, it’s relative.

When a tutorial says “edit src/main.js” and your editor swears that file doesn’t exist, nine times out of ten you’re running the command from the wrong directory, so the relative path is pointing somewhere unexpected. Run pwd, confirm where you are, and the mystery usually dissolves. This is exactly the situation where Environment variables explained matters too: a .env file is loaded relative to where you start your app, so running from the wrong folder can quietly hand your program no config at all.

Flags: the little dashes that change behavior

You’ve already used several flags. A flag (also called an option) is a little switch you tack onto a command to change how it behaves. Most come in two styles:

  • Short flags are a single dash and a letter: -a, -r, -f, -l. You can often jam them together, so rm -rf is -r and -f at once, and ls -la is -l and -a.
  • Long flags are two dashes and a whole word: --all, --recursive, --help, --version. Wordier, but easier to read in a script six months later when you’ve forgotten what -a meant.

A few short flags show up everywhere, so it’s worth knowing them by feel:

FlagShort forWhat it does
-rrecursiveApply to a folder and everything inside it
-fforceSkip the confirmations, just do it
-aallInclude hidden items
-llongShow the detailed, one-per-line view
-vverbose (or version)Print extra detail about what happened

When you don’t know what a command does or which flags it takes, ask it. Almost every command responds to --help:

npm --help
git commit --help

On macOS and Linux there’s also man (“manual”), which opens the full manual page for a command. Press q to quit out of it when you’re done reading, which is the one keystroke people get stuck on the first time.

man ls
# opens the full manual for ls; press q to get back to your prompt

Reading --help before you run an unfamiliar command, especially one someone pasted you from the internet, is the single best habit on this entire page.

The shells you’ll actually meet

You don’t need a position in the operating system holy wars. You just need to know which shell is in front of you, because the command set differs a little. Here’s the honest lay of the land.

On Windows you mainly meet two:

  • PowerShell ships with Windows and is genuinely capable, but some of its commands differ from the Mac and Linux world (it uses Get-ChildItem where they use ls, though ls is wired up as an alias for convenience). Most tutorials are written for the Mac and Linux commands, so pure PowerShell can mean small translation headaches.
  • Git Bash comes bundled with Git for Windows

    Heads up. You're leaving raindev.fyi

    This link heads to git-scm.com, an external site we don't control. Cool to keep going?

    Continue
    and gives you a Bash shell with the standard Unix commands (ls, rm, touch, and friends). For following along with most guides, it’s the path of least resistance.

On macOS, the Terminal app runs Zsh (pronounced “Z shell”) by default these days. It’s close enough to Bash that the commands in this guide all behave the same. If you’re on an older Mac you might be on Bash instead, and you won’t notice a difference at this level.

On Windows, there’s also WSL (Windows Subsystem for Linux), which is a real Linux running inside Windows. If you want the exact same commands and tooling that Mac and Linux developers use, with no translation, WSL gives you that. It’s the closest a Windows machine gets to “just do what the tutorial says,” and it’s worth setting up once you’re past the basics.

Classic terminal traps

The terminal is safe right up until it isn’t. Four mistakes catch nearly everyone at least once. Knowing them in advance is most of the protection.

Running rm -rf in the wrong directory. This is the big one. rm -rf deletes a folder and everything under it, instantly, with no confirmation and no recycle bin. The classic disaster is being one directory higher than you thought, or having a typo turn a path into something near the root. Before you ever run an rm -rf, run pwd and ls first and actually read them. Confirm you’re where you think you are and the target is what you think it is. If a stranger online tells you to run rm -rf on a path that isn’t clearly inside your own project, do not.

Confusing relative and absolute paths. A relative path like ../config means something completely different depending on your current directory. A command that worked perfectly in one folder does nothing useful in another, and the error message rarely says “you’re in the wrong place.” When a path-related command misbehaves, check where you are before you change the command.

Losing track of which directory you’re in. Half the “the file doesn’t exist” and “command not found for my script” problems come down to running a command from the wrong folder. The fix is a habit, not a trick: glance at your prompt, and run pwd whenever you’re unsure. It costs nothing and saves a lot of confusion.

Pasting a command without knowing what it does. Copying a command off Stack Overflow or a random blog and pasting it into your terminal is how plenty of bad days start. At minimum, read it. If there’s a piece you don’t recognize, run that part with --help first, or look it up. You don’t have to understand every flag perfectly, but “I have no idea what this does” plus pressing enter is the combination to avoid.

TrapWhat goes wrongThe habit that prevents it
rm -rf in the wrong placeA folder tree is gone for goodRun pwd and ls before deleting
Relative vs absolute path mix-upCommand targets the wrong locationCheck your directory before the command
Lost in the filesystem”File not found” with no clue whyGlance at the prompt, run pwd
Pasting unknown commandsYou run something you didn’t mean toRead it first; --help the unfamiliar bits

Why this turns into shipping

None of this is academic. The reason to get comfortable here is that every step of building and shipping a real project runs through the terminal.

You start a project with npm create astro or npx create-react-app, both terminal commands. You install your dependencies with npm install or pnpm install, terminal again. You run your dev server with npm run dev, save your work with git add, git commit, and git push, spin up a database with docker run postgres, and trigger a deploy to Cloudflare Pages

Heads up. You're leaving raindev.fyi

This link heads to pages.cloudflare.com, an external site we don't control. Cool to keep going?

Continue
or Railway

Heads up. You're leaving raindev.fyi

This link heads to railway.app, an external site we don't control. Cool to keep going?

Continue
from the command line. Every one of those is just typing a command, reading what comes back, and typing the next one.

The dozen commands on this page are the floor everything else stands on. Once moving around, making files, and reading --help are second nature, Git stops being scary, Docker stops being scary, and that blinking cursor turns into the place you get things done. Your laptop stops being a random code cave and starts being somewhere you can actually build and ship a project from.

So open the terminal you’ve been avoiding, run pwd, look at where you are, and cd into a project. That’s the whole job. You’re already doing it.