🧰 Set up your workshop
VS Code, Claude Code, a terminal you aren't scared of, git with a private GitHub repo, and the Windows traps that cost the fleet hours.
You'll leave with
- VS Code and Claude Code installed, signed in and working on your files
- A first project served on localhost and saved to a private GitHub repo
- Guardrails for the Windows and shell traps that silently corrupt files
Never shipped anything before? Good, start here. I'm a data person, not a 10× engineer, and I built the apps at traqqit.com with this setup: an editor, an AI that writes and runs code beside me, and an undo button for whole projects (the one I learned the hard way). Budget half an hour of reading and an afternoon of installs. You'll finish with a page running on your own computer and a copy saved privately online. You do this once.
⚡ The 60-second version (every word is explained below)
- Install VS Code, Node.js, Git, the GitHub CLI and Claude Code, in that order, plus a paid Claude plan and a free GitHub account.
- Reopen VS Code; each tool should print a version number.
- Open a new
myappfolder in VS Code, typeclaudein its terminal, sign in, switch to manual mode. - Ask Claude for a hello-world page; open it at the
http://localhostaddress it gives. - Run
gh auth login, set your git name and email, then ask Claude for a private GitHub repo. - On Windows, read the traps before anything edits your files.
Five installs, one afternoon
VS Code (the free editor) and Claude Code (the AI that writes and runs code beside you; it needs a paid Claude plan) are the two main installs. Three small helpers come with them: Node.js, Git and the GitHub CLI. You need a Windows or Mac computer, not a phone or tablet.
What are VS Code and Claude Code?
VS Code is a free code editor from Microsoft, a program for opening and changing the files an app is made of. Claude Code is Anthropic's AI coding assistant. It works inside your project folder: you describe a job in plain English, and it reads files, writes changes and runs commands.
Some installs happen in VS Code's terminal, so, after installing VS Code (item 1 below), meet it: choose View → Terminal, and a panel with a blinking cursor opens at the bottom.
What's a terminal?
A window where you type commands instead of clicking: type a line, press Enter, and the computer answers in text. On Windows, VS Code's terminal runs PowerShell (lines start with PS); on a Mac, zsh. Both are shells, programs that read what you type and run it.
Install in this order, accepting each installer's defaults:
- VS Code from code.visualstudio.com. (Mac: drag it into Applications.)
- Node.js from nodejs.org: the download marked LTS, for long-term support (24.x as I write this; a newer LTS is fine).
What are Node.js, npm and npx?
Node.js runs JavaScript, the programming language of web pages, outside a browser, so small tools written in it run on your computer. It brings npm, which downloads those tools, and npx, which runs one without a permanent install.
- Git. Windows: the installer from git-scm.com, default options; it also gives Claude Code a bash shell to work in. Mac: type
git --versionin the terminal and accept the offer to install the Command Line Tools (a few minutes).What are Git, a repo and GitHub?
Git records versions of your project's files on your computer. A repo (short for repository) is a folder Git tracks. GitHub is a website that keeps a copy of your repo online, private if you choose.
- GitHub CLI from cli.github.com, the download for your system. Its command is
gh.What's a CLI?
A command-line interface: a program you drive by typing commands instead of clicking. The GitHub CLI signs you in to GitHub and creates repos from the terminal.
- Claude Code, with Anthropic's own installer (official steps at code.claude.com/docs/en/setup). Paste the line for your system into VS Code's terminal (Ctrl+V, Mac Cmd+V) and press Enter. When it finishes, its last line is "Installation complete!"
irm https://claude.ai/install.ps1 | iex
curl -fsSL https://claude.ai/install.sh | bash
You need two accounts: a free one at github.com (your username appears in your repo addresses, so pick one you'd show anyone) and a paid Claude plan at claude.ai. Pro, about $20 a month, is enough to start; the free plan doesn't include Claude Code.
Now close VS Code completely and reopen it, so its terminal sees the new tools. In the terminal, type each line and press Enter:
node --version
git --version
gh --version
claude --version
Any number means that tool works. "Not recognized" (Windows) or "command not found" (Mac) means the install didn't finish, or the terminal is older than the install.
What's PATH?
The list of folders your terminal searches for commands. Installers add to it, but only terminals opened afterwards notice. claude still not found after a restart? The setup page above links to the fix, "Fix your PATH".
What it costs: the Claude plan, from today. From Your own server on, a small VPS (a rented, always-on computer: a few dollars a month on a long prepay, more at renewal) and a domain (your web address, about $10–20 a year). A mailbox on your domain may add a few dollars a month, once you add logins or a mailing list. The rest runs on free tiers or your own server, apart from fees if you take payments or publish to an app store.
🦥 Notice what's not on the list: a server. It comes in Your own server, once there's something worth putting on it.
📍 I added this lesson to this course for total beginners, since "even if you've never opened a terminal" has to start with installing the editor. Pictures of tools, like the chat boxes below, are labeled EXAMPLE: the tools keep changing their look, so follow the words, not the pixels.
The terminal without fear
The terminal looks hostile and is mostly harmless. Most of the "scary" commands in this course are ones Claude proposes, and it explains any of them when you ask. You'll be fine. Paste with Ctrl+V (Mac Cmd+V), and stop a command that keeps running with Ctrl+C. If a terminal asks for a password, it shows nothing as you type. That's normal.
Make your project folder with four commands, one line at a time:
pwd
mkdir myapp
cd myapp
code .
pwd should show your user folder (if not, type cd ~ first). code . opens myapp in VS Code; on a Mac, first press Cmd+Shift+P, type shell command and run Shell Command: Install 'code' command in PATH, once. (File → Open Folder works too.) If VS Code asks whether you trust the authors of the files in this folder, it's your own empty folder: yes. Open the terminal again if it's hidden (View → Terminal); its prompt now ends in myapp.
The eight commands you'll see again and again:
| Command | What it does | What you'll see |
|---|---|---|
pwd | Shows where you are, as a path (a folder's full address) | A path ending in myapp |
ls | Lists the files here | Nothing yet, in a new folder |
cd myapp | Moves into a folder; cd .. goes up one | The folder name in the prompt changes |
mkdir myapp | Makes a folder | A new folder |
cat index.html | Prints a file | Its text (Windows PowerShell may garble dashes and accents here; the file is fine) |
code . | Opens VS Code on this folder (the dot means "here") | A VS Code window |
node --version | Proves Node.js is installed | v24.x.x |
git status | Shows what changed since your last saved version | For now, fatal: not a git repository (correct until step 4) |
Start Claude Code
In the terminal of your myapp window, type claude and press Enter. The first time, it asks for a text style (any is fine), then a login method: choose Claude account with subscription, sign in in the browser that opens, and press Enter at Login successful. When it asks whether you trust this folder, choose Yes, I trust this folder, and press Enter through any other first-run notes. You should see a welcome header naming myapp above an input box: type there and press Enter. One run of claude, from start to exit, is a session.
Now look under the input box. New installs usually start in auto mode (auto mode on): a second AI model reviews each action and lets most run without asking you. While you're learning, press Shift+Tab until it says manual mode on. Then Claude asks before every edit and before most commands, roughly like this (EXAMPLE; wording varies by version):
Enter means Yes. Esc means not yet: Claude stops, you type "what does this do?" in the input box, and once it's explained you say "go ahead" and approve. That prompt is a feature, not a nag: ask before approving anything you can't explain. Choose plain Yes until you know a command well, and skip any option that switches to auto mode. It matters most once commands run on the computer hosting your live apps (from Your own server on).
To keep manual mode for every session, ask Claude: "In my user settings file, set permissions.defaultMode to default (that's manual mode)." Your next session should open with manual mode on. If Claude Code later offers auto mode, say no for now.
🛑 Never paste a password or an API token (a secret key that lets a program act as you) into the chat. It's sent to Anthropic and written into the session's saved history, and you can't take it back. If it happens, treat it as leaked: revoke it and make a new one.
Run it the right way: localhost, not double-click
Your first page is one file, index.html. Don't open it with a double-click: the browser loads it as file://, a file on your disk rather than a website. A path that starts with a slash, like /engine.js, means "from the top of the site", and under file:// the top is your whole drive. The file isn't there, so the app boots blank. (A plain hello-world page looks fine either way; the trap springs on your first real app.)
What's index.html?
HTML is the language a web page's content is written in. index.html is the file a web server hands out for a folder's address: your app's front page.
📍 This broke my own screenshot scripts, small programs that open an app in a hidden browser and photograph it before I ship. They opened First Bites and Baby Signs straight from the folder as file://, their slash-paths found nothing, and both apps booted blank. The fix: serve the folder first.
Instead, run a local web server: a small program that hands your files to the browser over http://, as a real server will.
What are localhost and a port?
localhost is your computer's name for itself. A port is a numbered door on a computer where a server waits, so http://localhost:3000 means "my own computer, door 3000". That address only works on your machine.
In Claude's input box:
EXAMPLE — YOU ASK CLAUDE CODE
What's happening underneath: Claude wrote one file and started npx serve, a small server tool, in this folder. It answers each request (a browser's ask for a file) with the file asked for. Claude then tested it with curl, a command that fetches an address and prints the reply, and got 200 OK, the web's "all good". Open the address: you should see "Hello, world". If Claude ever claims success without a check, ask for one.
To run a server yourself, open a second terminal (the + in the terminal panel) and run:
npx serve
Type y if it asks to install it. A box appears with the address:
Open the Local address. If port 3000 is already in use (Claude's server is probably holding it), serve picks another port and says so in the box, so always open the address it shows. Ctrl+C stops it. On Windows, if PowerShell says running scripts is disabled on this system, the fix is under Windows traps below; if a firewall box asks about Node.js, Cancel is fine, because localhost works either way.
🦥 One HTML file, served as it is. The Baby Signs app itself is one HTML file plus a catalog file and a logic file. Add structure when the app needs it (Build static-first).
Git is your memory, even if you deploy by copying files
Later you'll deploy: copy your files to a server so the world can open them (Deploy behind one front door). Copying files is a fine way to deploy, but only git remembers: it shows what changed, undoes mistakes, and lets you read every edit an AI made, line by line. The habit is push first, deploy second, so GitHub always matches what's live. A private repo is fine: nobody sees it unless you invite them, and it's free.
What are a commit, a push and a diff?
A commit is a saved snapshot of your project, with a short message saying what changed. A push uploads your new commits to the copy on GitHub. A diff is the list of lines that changed between two versions, removed ones in red and added ones in green.
📍 One of my side projects, an unlisted browser game, ran for days without git. A cleanup's deletions were backed up only to a temporary folder, and when a bug broke its multiplayer, there was no diff to show what had changed. So here, git comes before your first line of code.
Two things you type yourself
Claude can't answer the questions these ask, so type them yourself, once, in a free terminal (click + for a fresh one if the others are busy with Claude or a server). First, sign the GitHub CLI in:
gh auth login
Answer with the arrow keys and Enter: GitHub.com, then HTTPS (the encrypted way web pages travel), then Yes to authenticate Git with your GitHub credentials, then Login with a web browser. Copy the one-time code, press Enter, paste it into the page that opens and authorize. The terminal should then say Logged in as, with your username.
Second, tell git who you are, or your first commit stops with Author identity unknown. Use GitHub's no-reply address, which keeps your real email out of the history: on GitHub, click your picture (top right) → Settings → Emails, tick Keep my email addresses private, and copy the address ending in @users.noreply.github.com. Replace both values with yours; they print nothing when they work:
git config --global user.name "Your Name"
git config --global user.email "YOUR_ID+USERNAME@users.noreply.github.com"
Now ask Claude:
EXAMPLE — YOU ASK CLAUDE CODE
What's happening underneath: git init turns the folder into a repo, the commit saves your first snapshot, and gh repo create makes the private GitHub repo and pushes to it. Open its address yourself, with your username in place of YOUR_USER. .gitattributes, a small settings file for git, pins line endings (Windows traps explains why) and should contain this line:
* text=auto eol=lf
Because you chose HTTPS at login, pushing needs no extra keys. If a push ever says Permission denied (publickey), the repo's remote (the GitHub address it pushes to) uses SSH, a key-file login you haven't set up. Ask Claude to switch it to HTTPS. Underneath, it's these three commands (replace YOUR_USER):
git remote set-url origin https://github.com/YOUR_USER/myapp.git
gh auth setup-git
git push -u origin HEAD
From now on, VS Code's Source Control panel (the branching icon in the left bar) lists every changed file; click one to see its diff. To undo, ask Claude (say, "undo my changes to index.html since the last commit") and read the command before you approve it.
🛑 git restore, the usual undo, throws away uncommitted edits for good, so commit before every big ask. And private isn't secret-safe: never commit a password or token. When your app gets secrets, they live in an env file (a list of NAME=value settings your code reads), listed in .gitignore, a file of names git must never track.
🦥 One line of history: commit, push. No branches (parallel versions of a project) until a second person works on the app.
Windows traps the fleet paid for
I build the fleet on a Windows laptop, and Windows charged tuition. The first three traps are Windows-only, so Mac users can skip to line endings.
PowerShell runs commands; it doesn't edit files
Windows PowerShell 5.1, built into Windows and used by VS Code's terminal unless you've installed PowerShell 7, reads files in an old Windows encoding. So a command that reads a UTF-8 file, changes it and writes it back as UTF-8 turns every em dash (—) into —. Adding -Encoding utf8 to the write doesn't help: the damage happened on the read. Nothing errors, plain English lines look unchanged in a diff, and the garbage surfaces later on your live page.
What are UTF-8 and mojibake?
UTF-8 is the standard way to store text as bytes, accents, dashes and emoji included. Mojibake is the garbage you get when bytes are read with the wrong encoding, like — where a dash should be.
So edit files in VS Code, with Claude's edit tool or with node, and use PowerShell only to run commands. Claude Code on Windows can use PowerShell too, so give it a standing rule: "Create CLAUDE.md with this rule: on Windows, never change files with PowerShell's Get-Content or Set-Content; use your edit tool or node." CLAUDE.md is the instructions file Claude Code reads by itself at the start of every session (Work with Claude Code builds on it). Already damaged? Search for †with Ctrl+Shift+F (Mac Cmd+Shift+F) and replace each sequence, like — with —, in the editor, never with another PowerShell pass.
"Running scripts is disabled on this system"
If npx or npm fails in PowerShell like this:
run this once, then type Y and press Enter when it asks to confirm:
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
The execution policy is a PowerShell safety setting that blocks script files, and on Windows npx is one. RemoteSigned, for your user only, runs scripts on your computer and still blocks unsigned ones downloaded from the internet.
curl is curl.exe
The garbled-text check below and later lessons use curl. In Windows PowerShell, plain curl is a different command in disguise: type curl.exe. Git Bash and Macs have the real one.
Line endings: a small edit, 700 changed lines
Windows ends each line of text with two invisible characters (CRLF); Linux and Mac use one (LF). When a tool rewrites a file in the other style, git sees every line as changed.
📍 On my medical price tool, a script rewrote a test file and quietly switched it from CRLF to LF. A small edit showed up as about 700 changed lines, burying the real one. It happened more than once before it became a rule.
The rule is step 4's one-line .gitattributes: git stores text files with LF, whatever your editor saved, which is also what your Linux server will want. A warning that CRLF will be replaced by LF is the rule working. Before each commit, check the size of the change:
git diff --stat
A one-line edit should show one file and a line or two. Hundreds means something rewrote the whole file: git diff --ignore-cr-at-eol --stat shows the change without line-ending noise, and Claude can restore the original endings before you commit.
Garbled text? Check before you fix
When garbled text was reported on one of my sites, the file was clean UTF-8 and the server already said charset=utf-8. Nothing was broken, and "fixing" it could have created a real bug. Check two things first:
- The file. In VS Code, the bottom-right of the status bar shows its encoding (
UTF-8). If the text looks garbled in VS Code too, the file itself is damaged. - The server's header, a labeled line of information sent with each response (the server's reply). Try it on your page while a server runs (Mac or Git Bash:
curl, notcurl.exe):
curl.exe -sI http://localhost:3000
Never point a script at a version folder
One of my scripts called a tool by its full path inside a VS Code add-on's folder, version number and all. Add-ons update themselves and delete old folders, and two pinned paths vanished within days. Install tools properly and call them by name (claude, node, git). If Claude writes a path containing a version, like tool-2.1.259, ask it to find the tool by name instead.
Check you're ready
Three checks, all passing before the next lesson:
- Claude answers inside your project. Ask it "Which folder are you working in, and what files are here?" It should name
myappand listindex.htmland.gitattributes(plusCLAUDE.mdon Windows). - Git has your first commit. In a free terminal,
git log --onelineprints one line, likea1b2c3d (HEAD -> main, origin/main) First page.originis git's name for the GitHub copy, soorigin/mainmeans GitHub has it too (your branch may be calledmaster; either is fine). - The page opens at a localhost address. With a server running,
http://localhost:3000shows "Hello, world".
If one fails, paste the exact error into Claude and ask what it means before asking for a fix: you learn the cause and can judge whether the fix fits.
EXAMPLE — YOU ASK CLAUDE CODE
What's happening underneath: Claude tested the address and listed the folder before answering. If an explanation comes with no check like that, ask "how do you know?"
Do it with Claude: the prompts
Every new app starts the same way: open its folder, start claude in manual mode, and send these one at a time.
- Create a hello-world index.html here, start a local web server and tell me the URL to open.
- Initialize git here, add a .gitattributes that forces LF, make a first commit, then create a private GitHub repo called myapp and push over HTTPS.
- Explain each command you ran, in one line each.
EXAMPLE — YOU ASK CLAUDE CODE
git add -A and git commit -m "First page": save every new or changed file as a labeled snapshot.
gh repo create myapp --private --source=. --push: makes a private GitHub repo and uploads that snapshot.
git log and gh repo view: my two checks, the commit list and the repo's privacy.
What's happening underneath: Claude reads your files on its own, then proposes commands and edits. In manual mode, every edit and most commands wait for your OK; plain reads, like listing a folder, don't. The third prompt turns approving into learning: if an explanation doesn't match what you saw, ask again.
🦥 Left alone, an AI builds you a mansion when you asked for a shed. End big asks with "Build the smallest version that works, then tell me what you skipped." The laziest thing that works makes that the default.
Your turn
- In a freshly opened VS Code terminal, run
node --version,git --version,gh --versionandclaude --version. Done when all four print a version number. - Start Claude in
myappwithmanual mode onunder its input box. Done when, asked which folder it's in, it namesmyapp, and you've approved a command only after asking what it does. - Run
npx serveyourself in a second terminal. Done when its address shows "Hello, world", and after Ctrl+C a refresh says the site can't be reached. - Open
https://github.com/YOUR_USER/myapp. Done when it showsindex.htmland.gitattributeswith a Private label, andgit log --onelineshows your first commit. - Open
index.htmlfrom VS Code's file list (left side), change one word, save (Ctrl+S, Mac Cmd+S) and rungit diff --statin a free terminal. Done when it reports one file and a line or two, and you've asked Claude to commit and push the change. - Windows: add the PowerShell rule to
CLAUDE.mdand getnpx serverunning in PowerShell. Mac: getcode .to open VS Code. Done when the rule is in the file, or the command works.
Next, Work with Claude Code: prompts that get small, working results, a notes file that stops Claude repeating old mistakes, and the habit of checking its work instead of trusting it.