Skip to content

Running the code locally ​

Use this page to run an extracted Learn AI Agents project on your computer and get an answer from the OpenSwap agent with your own provider key. Two things differ from Scrimba: you give the project its three AI values in a .env file instead of Scrimba's settings, and the project does not reload by itself after you change a file. The Scrimba version keeps working whether or not you do this.

What you need first ​

Install a supported LTS version of Node.js. Node 24 is recommended, Node 22 also works, and both include npm. Check that both commands print a version. Your version numbers may be different:

bash
$ node --version
v24.18.0
$ npm --version
11.18.0

You also need the three values you saved in Scrimba's environment settings: AI_KEY, AI_MODEL and AI_URL. If you no longer have them, or never set them up, provider setup walks through getting a key from OpenAI or OpenRouter.

JunoWhat you need first Install the LTS version of Node.js, which includes npm, and check that node --version and npm --version both print a version.

Then have your key, model and URL from Scrimba ready to copy. They are the only values this project needs.

JunoWhat you need first The project has two halves: an Express server that holds your key and calls the provider, and a Vite server that sends the page to your browser. One command starts both, and the three values are read by the Express half only.
JunoWhat you need firstenvironment.js loads .env with loadEnvFile from node:process, which Node added in 20.12. On an older Node it stops with a message naming that version instead of starting with empty values, so that message always means change Node, not .env.

Install the packages ​

Open a terminal in the extracted project folder. It is the one containing package.json, server.js and environment.js:

bash
$ cd path-to-your-extracted-project

Install the packages:

bash
$ npm install
added 106 packages, and audited 107 packages in 6s

The number of packages depends on the lesson. npm may also list vulnerabilities, or warn that some packages have install scripts. Neither stops the project from running.

JunoInstall the packages Open the terminal in the folder that contains package.json, then run npm install. It ends by saying how many packages it added.

If npm says it cannot find package.json, you are in the wrong folder.

JunoInstall the packages The download includes package-lock.json, so npm install gets the same package versions the lesson ran with on Scrimba. Everything it installs goes into node_modules in this folder, including the tools that start the two servers.
JunoInstall the packagesnpm start runs concurrently, which lives only in this folder's node_modules. Starting before installing fails with concurrently: command not found, not with an error about your code.

Create your .env file ​

The project makes the file for you. Start it once:

bash
$ npm start

The first time, the server finds no values, creates .env beside package.json, and stops with this message:

text
Error: Missing environment variables: AI_KEY, AI_MODEL, AI_URL.
Created .env with the required variable names. Complete it, then restart the app.
Setup guide: https://docs.scrimba.com/ai-agents/running-locally

Vite keeps running and prints an address, but the page cannot work yet. Press Ctrl+C to stop everything, then open .env. It has one empty line per value and a commented port line at the end:

dotenv
AI_KEY=
AI_MODEL=
AI_URL=
GITHUB_TOKEN=
# PORT=3001

Fill in your three values straight after each =, with no spaces or quotes. With OpenAI, the course default, that looks like this:

dotenv
AI_KEY=your-api-key-here
AI_MODEL=gpt-5.4-nano
AI_URL=https://api.openai.com/v1
GITHUB_TOKEN=
# PORT=3001

GITHUB_TOKEN appears only in lessons that check projects on GitHub. You can leave it empty; GitHub then answers with a lower rate limit. Leave the # PORT=3001 line as it is.

Never commit your .env file

If you put this project in Git, create a .gitignore beside package.json before your first commit, so your key and the installed packages stay out of the repository:

txt
.env
node_modules

A key that reaches a repository stays in its history even after you delete the file; the only fix is to delete the key at your provider and make a new one. The Git handbook covers the habit in ignoring files and good habits.

JunoCreate your .env file Run npm start once so the project creates .env, press Ctrl+C, then copy your key, model and URL into the three empty lines and save.

If it says it created .env again next time, your file has a different name, such as .env.txt.

JunoCreate your .env file On Scrimba, the editor hands these values to the running project. Here, environment.js runs first in server.js, reads .env, and refuses to start the server while a required value is empty, so a missing value shows up before any request is made.
JunoCreate your .env file The file is created only when no file named .env exists, so a file saved as .env.txt is ignored and a fresh empty .env appears beside it. The values are read once, at start, which is why every edit needs a restart.

Start the app and send a request ​

Start the project again:

bash
$ npm start

Both servers print into the same terminal. Ticks for your three values and two addresses mean both started:

text
Environment check:
✓ AI_KEY: configured
✓ AI_MODEL: gpt-5.4-nano
✓ AI_URL: https://api.openai.com/v1
○ Optional environment not configured: GITHUB_TOKEN
OpenSwap server running at http://localhost:3001

  VITE v6.4.3  ready in 150 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose

Open the Local address, not the 3001 one, and use the page as you did in the lesson. In the OpenSwap lessons, pick a software name or type a request, then click Swap it. The button reads Loading... while the agent works, and an answer appearing means your key, model and URL all work. If your page has a Run Agent button instead, click it; the agent's output appears in the terminal, not on the page.

If the page shows an error, or nothing happens, the reason is in the terminal; the troubleshooting below matches each message.

The project does not reload by itself. After you change any file, press Ctrl+C, run npm start again, then refresh the browser.

JunoStart the app and send a request Run npm start, open the Local address, and send one request.

If the page shows an error, look at the terminal for the lines that appeared when you clicked, and find them under the troubleshooting heading.

JunoStart the app and send a request The page only ever calls addresses starting with /api on the Vite server, and Vite passes them on to Express. Express sends the request to your provider with your key, so the key never reaches the browser.
JunoStart the app and send a request Every server failure becomes the same generic message in the browser: the route logs the real error with console.error and answers with a 500. Vite's file watching is switched off, so it keeps serving the first version of each file it sent, and Express never reloads, which is why a change needs a restart.

When port 3001 is taken ​

Express listens on port 3001. If something else already uses it, most often another lesson you left running in a different terminal, the server still prints its server running at http://localhost:3001 line, then quits without an error. The page's requests then reach the other program: you may see an error such as is not valid JSON, or answers from the other lesson.

Stop the other project with Ctrl+C in its terminal. To run both, give this one another port: open .env, remove the # from the last line, and change the number:

dotenv
PORT=3101

Press Ctrl+C and run npm start again. The server line now shows 3101, and Vite sends the page's requests there, because it reads the same line.

Vite's own port moves by itself. If 5173 is busy, Vite prints Port 5173 is in use, trying another one... and a Local address such as http://localhost:5174/, so always open the address it prints.

JunoWhen port 3001 is taken If the page shows an error or another lesson's answers, look for another terminal still running npm start and stop it with Ctrl+C.

To keep both running, change # PORT=3001 to PORT=3101 in this project's .env and restart.

JunoWhen port 3001 is taken Express and Vite's forwarding both read PORT from the same .env, so changing that one line moves both. Vite's own port is separate and needs no setting.
JunoWhen port 3001 is taken In Express 5, app.listen passes a listen error to its callback, and this project's callback ignores the argument and logs the running line. The process then has nothing to keep it alive and exits, so the terminal shows success while Vite forwards to whatever owns 3001.

If something doesn't work ​

concurrently: command not found (on Windows, 'concurrently' is not recognized): the packages are not installed in this folder. Run npm install there, then npm start.

Missing environment variables: followed by names: those lines in .env are still empty, or the file was not saved. Fill them in and start again.

It says Created .env again, although you made one: your file is not named exactly .env in the folder with package.json. A file saved as .env.txt does not count. Put your values into the new .env and delete the other file.

The page shows Unexpected end of JSON input: the Express server is not running, and the terminal shows [vite] http proxy error. Scroll up to the first error above the Vite lines; it says why Express stopped.

The terminal shows 401 Incorrect API key provided (OpenAI) or 401 Missing Authentication header (OpenRouter): the provider rejected AI_KEY. Copy the key again from your provider, save .env and restart.

The terminal shows 429 and exceeded your current quota: the key works, but the account has no credit to spend. Add credit with your provider and try again.

The terminal shows a model-not-found error: AI_MODEL and AI_URL belong to different providers, for instance an OpenAI model ID with OpenRouter's URL. Change all three values together when you switch providers.

"Local environment loading requires Node.js 20.12 or newer." Your Node is too old for the project's .env loader. Install the current LTS release from nodejs.org, then run npm start again.

In lessons with a chat sidebar, a failed request can leave a chat called New conversation. It is empty and does no harm.

Everything looks right and it still fails. Bring it to the course Discord, with what you ran and what came back. Setup problems are almost always specific to one machine, and someone has usually hit yours already.

JunoIf something doesn't work Read the terminal first: find the first line that starts with Error or shows a number like 401, and match it to a bold heading above. Restart with npm start after every change to .env.
JunoIf something doesn't work The failures come in order: packages missing, values missing, Express not running, then the provider turning down the key, account or model. The first one you hit tells you which step to go back to.
JunoIf something doesn't work A 401 means Express started with all three values and reached the provider at AI_URL, so .env loaded; that provider turned the key down. A key from the other provider gets the same 401, which is why the three values change as one set.