Module 26 · 50 min

Start Here: Run the App You Will Build

You can open a terminal, get a copy of the app, run it with no key and no cost, and type a message that comes back through a server you can see.

The app this track builds is a chat window with an agent behind it, and you are going to write every part of it yourself. But nobody builds an app they have never seen run. So before any of that, we get it running on your own machine, with your own hands on it. That is this page’s whole job. It assumes you have never typed a command, and it stops to explain each word the first time it is needed.

Three words carry everything below, so let’s pin them down first. A file is a named lump of text or data on your disk. A folder is a named box that holds files and other folders. A program is a file whose text is instructions, and running it means handing that file to something that carries the instructions out. You already run programs every day by clicking icons. Here you will run them by typing their names.

Where do you type them? In the terminal: a window with no buttons at all, where each line you type is one command, meaning the name of a program followed by whatever you want to hand it. On macOS it is called Terminal, on Windows it is called PowerShell, on Linux it is usually called Terminal too.

Before you open the real one, rehearse on a pretend one. The box below looks like a terminal and takes typed commands, but it is practice: every answer is a script written into this page, and nothing you type in it touches your computer. Run the six commands listed above it, in order, and watch what each one prints. The folder it pretends to stand in contains a copy of the app called chat-workbench, which you do not have yet; the rest of this page is you getting the real one.

Try these, in order
  1. pwd prints where you are standing.
  2. ls lists what is here: two folders, one of them the app.
  3. cd chat-workbench moves you into the app folder. Nothing prints when it works.
  4. ls the same command in a different folder gives a different answer.
  5. node --version asks a program to state its version. You will run this for real below.
  6. clear wipes the screen. This one works for real, here and everywhere.
practice terminal the responses are scripted
A practice terminal. The commands are real; the answers are a script, and the folder it pretends to stand in is the one this page is about to help you create.

That is the whole motion: stand somewhere, look around, move, look again, ask a program a question. When the list is done, open your real terminal and leave it open. Everything below happens in it.

flowchart LR
t["your terminal<br/>you type commands"] --> f["the folder<br/>a copy of the app"]
f --> s["the server<br/>a program that waits"]
s <--> b["your browser<br/>the chat window"]
Four things, left to right, in the order you will meet them. You type in the terminal, which starts the server, which sits in the folder you copied; the browser and the server talk to each other while both stay running.

A terminal is always standing in one folder

Here is the thing that causes more first-week confusion than anything else on this page: every terminal window is standing somewhere. It stands in one folder, and every command you type acts on that folder unless you say otherwise. That location is the working directory. To see where you are:

pwd

One line comes back: the path, the full address of the folder you are standing in, such as /Users/you or C:\Users\you. The same command works on macOS, Linux and PowerShell alike. Now, to move somewhere else, type cd and the path you want:

cd Documents

cd is short for change directory, because directory is the older word for folder and you will meet both everywhere. Notice that nothing prints when it works: in a terminal, silence usually means success. Run pwd again and the line has changed. That is the whole navigation system.

Install the two programs you need

Two programs have to be on your machine before the app will run, and neither one is Claude.

The first is Node, the program that reads a file of JavaScript instructions and carries them out. The app is written in JavaScript, so without Node there is nothing to run it with. Download it from nodejs.org and pick the version marked LTS, short for long-term support: that is the one that keeps working for years. Run the installer. Module 13 covers the same install at more length and then writes a program with it, and it is the next page in this track’s reading order after this one.

The second is git, the program that records versions of a folder and lets you fetch a copy of somebody else’s. Download it from git-scm.com/downloads, which is the same site the Claude Code setup page links to for Windows. On macOS, typing git --version may offer to install it for you.

Then close the terminal and open a new one, because a terminal only learns what programs exist when it starts. Check all three:

node --version
npm --version
git --version
v22.15.0
11.3.0
git version 2.49.0.windows.1

Those are the versions this page was written against, on Windows, on 2026-08-30. Your numbers will differ and that is fine, as long as the Node one starts with v22 or higher: the Claude Code documentation records that as of v2.1.198 its own npm package requires Node.js 22 or later, and this app is built to the same line. The git version line has no windows in it on a Mac.

Wait, you installed two programs and checked three. The middle one, npm, arrives with Node: it is the program that fetches packages, code other people wrote that your project borrows. You did not install npm and you do not need to. If a new terminal still says the command was not found, the install went somewhere your terminal does not look, and the install troubleshooting page has the fix for that on each system.

Copy the app onto your machine

Right now the app lives on somebody else’s computer, and you need your own copy. Git’s word for a folder it is recording versions of, together with its whole history, is a repository. Copying one down is called cloning, and git clone is the command that does it: you hand it an address, and it leaves a new folder beside you with every file in it.

git clone https://github.com/01000001-01001110/chat-workbench.git
cd chat-workbench

Replace the angle-bracket part with the repository’s address. When it finishes you have a folder called chat-workbench, and the second line walks you into it. Run pwd if you want to see that you moved.

One more thing about that folder: its history has named points in it. A tag is a name git has pinned to one moment in the history, and git checkout <tag> puts every file in the folder back the way it was at that moment. This track’s tags are named after its modules, so whatever page you are on, there is a matching point in the history you can return to at any time.

git checkout module-29

module-29 is the earliest tag on this repository, and the app at that point is a chat window with one agent behind it, which is exactly as much as this page needs. The files on disk are now what they were at that tag. Git prints a short advisory when you do this, because you are looking at a fixed point in the history rather than at the latest work; read it and carry on. Nothing you have on disk is lost by moving between tags.

Now fetch the packages the app borrows:

npm install
added 118 packages, and audited 121 packages in 3s

34 packages are looking for funding
  run `npm fund` for details

1 high severity vulnerability

To address all issues, run:
  npm audit fix --force

Run `npm audit` for details.

That created a folder called node_modules holding all 118 of them. The counts and the timing will differ on your machine. The audit lines are npm reporting on the security of what it fetched, and the urge to run the fix it suggests is natural. Resist it for now: npm audit fix --force is a command that changes versions underneath you, and this app is pinned to versions the course tested.

Start it in fake mode

Here is the question that usually stops people at this point: does running this cost money? Not today. The app can run in two ways. In the normal way it talks to Claude, which needs a key and costs money per message. In fake mode it answers from a canned script instead, so no model is called, nothing is billed, and the whole app still runs end to end. Every page of this track runs in fake mode first.

You choose between them with an environment variable: a named value the terminal hands a program when it starts. Setting WORKBENCH_FAKE_SDK to 1 selects fake mode.

In bash and zsh, on macOS and Linux, put the name and value in front of the command and it applies to that one run:

WORKBENCH_FAKE_SDK=1 npm run dev

PowerShell has no such form, so set it on its own line first. It then applies to every command in that window until you close it:

$env:WORKBENCH_FAKE_SDK = "1"
npm run dev

Either way you get npm’s own two lines about which script it is running, then one line from the app itself, which is data rather than a sentence:

{"t":"...","level":"info","event":"listen","url":"http://127.0.0.1:3000","workspace":"/home/you/chat-workbench/workspace","client":"/home/you/chat-workbench/client/public","fake":true,"fakeDelayMs":120,"permissionMode":"dontAsk","settings":"isolated"}

The two paths are wherever you cloned the folder, and the timestamp is the moment you started it. That format with the curly braces and the quoted names is JSON, and the app writes its log this way so that a program can read it as well as you.

The terminal now sits there without giving you back the line where you type, and your first instinct will be that something is stuck. Nothing is stuck. That program is a server: a program that does not finish, because its job is to wait to be asked for something and answer. When you do want to stop it, click on that terminal window and press Ctrl and C together.

http://127.0.0.1:3000 is where it is waiting. 127.0.0.1 means this computer and nowhere else, so nothing you do here is reachable from the internet. 3000 is the port, a numbered door on your machine, and the server has taken that one.

Type a message

Open a browser and go to http://localhost:3000, which is the same address by its friendlier name. The chat window loads. Type Say hello. and press enter, and the reply arrives in pieces rather than all at once, which is what the finished app does with a real model too:

Fake mode is on, so no model was called. This is turn 1 of one session. You said: Say hello.

Send another and it answers again, counting turns as it goes. Stop and trace what happened: that reply came out of a file in the folder you cloned, travelled to your browser through the server that terminal is still running, and cost nothing. Everything in this track is that path getting longer.

Build

Four steps, in this order. Every Build box on this track climbs the same ladder.

  1. Run it. Everything above, ending with a reply in the browser.
  2. Read one file. Open README.md in the folder and find the sentence that says fake mode needs no API key and makes no billable call.
  3. Change one line. Open client/public/index.html, find the line near the top reading <title>Chat Workbench</title>, put your own name in place of those two words, save, and reload the browser. The browser tab now says it. There is no build step in this app, so the file you edited is the file the server hands out.
  4. Build. Stop the server with Ctrl+C, start it again with the same command, and reload. Your name is still there. You have now changed a running program and proved the change survives a restart, which is the whole loop the rest of the track repeats.
The mistake most people make first

You leave the server running, open a second terminal because you want to type something else, and start the app again there. This is what you get:

node:events:496
      throw er; // Unhandled 'error' event
      ^

Error: listen EADDRINUSE: address already in use 127.0.0.1:3000

Followed by a dozen lines of file names and numbers, and at the bottom Failed running 'src/index.js'. It reads like the app is broken. It is not, and the first copy is still running perfectly. EADDRINUSE is short for “address in use”: port 3000 is one door, the first server has it, and a second program cannot take a door that is already taken.

The fix is to stop one of them. Go back to the first terminal and press Ctrl+C, or leave it alone and use the second terminal for something else. One more detail worth knowing, because it looks like a second bug: the development command watches your files for changes, so after printing that error it stays open instead of returning you to a prompt. Press Ctrl+C there too.

Does this travel?

All of it, and further than anything else on the site. Git is the same program with the same commands in every language and every company; clone, tag and checkout mean what they mean here whatever you work on next. Every language has a runtime you install and a package manager that fetches other people’s code. Every web application anywhere is a server on one side and a browser on the other, talking over a port. The one part that is local to this app is the name WORKBENCH_FAKE_SDK, and even the idea behind it, a switch that runs the whole system without touching the expensive thing, is standard practice.

Check yourself

  1. You open a terminal, type npm install, and it reports that it could not find a package.json. Nothing is wrong with the app. What is wrong, and which command tells you so?
  2. Fake mode called no model and cost nothing, yet a reply still appeared in the browser. Name every program that had to be running for those words to reach the page.
  3. You change <title> in index.html and reload, and the tab still shows the old name. Give two explanations that fit, and say which command or click would tell the two apart.