27 min read

Self-Host B4.run and Connect It with Localtonet

Install and verify a B4.run Node.js agent server, confirm its current port, and provide remote access through a Localtonet HTTP tunnel.

B4.run on a local computer connected to a remote browser through a Localtonet HTTP tunnel.
Localtonet routes remote HTTP requests through an outbound tunnel to the verified local B4.run service.
Self-Hosting ยท B4.run ยท Localtonet ยท 2026

Run a TypeScript AI agent server locally, verify it, then make it reachable through a controlled public HTTP endpoint

B4.run is a TypeScript framework for building agents and workflows around LangGraph.js using file-system routes, generated types, tools, testing conventions, persistence primitives, and runnable build targets. In this guide, we create a B4.run application with the official Node.js scaffold, test it before startup, identify the actual development port used by the installed release, and verify the server locally. We then connect that confirmed local service to an HTTP tunnel with Localtonet, without requiring inbound router port forwarding, a public IP address, or VPN setup. Because B4.run is evolving and its generated scaffold can change, the workflow deliberately verifies scripts and ports instead of assuming that an observation from one release applies to every installation.

๐Ÿ”’ Verify locally before allowing remote access ๐ŸŒ Publish the confirmed HTTP service with Localtonet โšก Start from the official B4.run application scaffold

How B4.run and Localtonet fit together

B4.run helps TypeScript teams organize AI agents, workflows, raw graphs, and chains as application routes. A supported entry placed under a route in src/app/ is discovered by the framework. Shared tools can live in src/tools/, while route-local tools can be placed beside a route. B4.run generates TypeScript declarations for routes, parameters, state, and tools where the relevant definitions are discoverable.

The framework builds on LangGraph.js rather than replacing it. LangChain integrations remain available for the built-in agent path, while raw graph and chain routes control their own imports and provider behavior. This makes B4.run a reasonable fit when a TypeScript project wants LangGraph.js together with file-system conventions, generated types, fixture-backed testing, local persistence primitives, and build targets. It is not a Python framework, a model provider, or a hosted infrastructure service.

The self-hosting boundary matters. B4.run can emit a runnable Node.js server and deployment artifacts, but the application operator remains responsible for the machine, runtime, storage, credentials, authentication, and network exposure. During development, the generated server normally begins as a local service. That is the right place to test it because failures can be separated into application problems and remote-connectivity problems.

After the local server works, Localtonet can provide the connectivity layer. Our client runs on the machine that hosts B4.run, or on another device that can reach it over the local network. The client establishes an outbound connection to a Localtonet relay server. An HTTP tunnel then maps a public HTTPS address to the selected local IP address and port. This does not require an inbound router rule, firewall port-forwarding change, VPN configuration, or public IP address.

๐Ÿงฉ Application layer B4.run supplies the TypeScript application conventions, route discovery, generated types, local development workflow, testing support, persistence primitives, and runnable build output.
๐Ÿ–ฅ๏ธ Runtime layer Node.js executes the generated application on the self-hosted machine. The operator manages that process, its files, provider credentials, storage, and updates.
๐ŸŒ Connectivity layer With Localtonet, an HTTP tunnel forwards an assigned public HTTPS address to the verified local B4.run HTTP listener.
๐Ÿ” Access-control layer The application owner must decide who should reach the service and enforce appropriate authentication, authorization, tool limits, secret handling, and approval boundaries.
Installation and network exposure are separate milestones

A successful scaffold or test run does not prove that the development server is running. A running local server does not prove that a Localtonet tunnel is active. Verify each layer independently: installation, tests, local startup, local HTTP access, tunnel status, and public access.

Prerequisites for the B4.run research starter

Prepare the development machine before generating the project. The official B4.run quickstart requires Node.js 24 or later. The scaffold command is executed through npm, so npm must also be available in the same shell. Use a development machine where you can create files, install npm dependencies, and keep a Node.js process running.

Required software and access

  • Node.js 24 or later: an older major version does not satisfy the documented requirement.
  • npm: used to run the application generator and install dependencies.
  • A writable project directory: the scaffold creates a new directory for the application.
  • Network access during installation: npm must retrieve the selected generator and project dependencies.
  • A browser or HTTP client: needed to verify the development server locally.
  • The Localtonet client: required only after the B4.run server has passed local verification.
  • A Localtonet device auth token: this identifies the client device and must be kept private.

Confirm the installed runtime before scaffolding:

node --version
npm --version

The Node.js output must report major version 24 or later. If the command is missing or reports an older release, install or select a compatible Node.js version using the method appropriate for your operating system. The B4.run evidence used for this guide does not prescribe one universal Node.js installation method, so we do not provide an operating-system-specific package-manager command that may be wrong for your environment.

Decide what the first deployment is for

A local development server is appropriate for evaluation, route development, fixture-backed testing, and controlled demonstrations. It should not automatically be treated as a production deployment. Before exposing an agent service to untrusted users, identify its model-provider boundary, tools, writable paths, persistence, approval behavior, authentication, rate limits, and expected audience.

B4.run supports a deterministic fixture-backed test path. Committed fixtures replay recorded responses, and an unmatched interaction fails instead of silently calling a provider. Live and recording modes are explicit opt-ins. This means the documented initial test workflow can validate the generated starter without requiring a live provider call, but using an agent against a live model can still require provider-specific credentials.

Do not place credentials in commands, source control, or tunnel configuration

Model-provider credentials and other secrets are application concerns. The exact required variables depend on the generated release, selected starter, and provider. Inspect the generated project documentation and configuration before enabling live execution. Never paste a Localtonet auth token, model key, private endpoint, or other credential into public logs or examples.

Install the B4.run application

The official quickstart uses the current create-b4-app package. The following sequence preserves the documented scaffold, dependency-installation, and test flow. The project name my-agent is an example and can be replaced with a suitable directory name.

1

Confirm Node.js 24 or later

Run node --version and verify that the installed major version is at least 24. Also confirm that npm --version returns successfully.

2

Generate a new B4.run project

From the parent directory where the project should be created, run npm create b4-app@latest my-agent. The @latest tag resolves at installation time, so record the generated package versions if repeatability matters.

3

Enter the generated project directory

Change into my-agent before running project-specific npm commands.

4

Install the project dependencies

Run npm install inside the generated directory and allow npm to complete before continuing.

5

Run the generated test suite

Run npm test. Resolve installation or test failures before starting the development server or creating a public tunnel.

npm create b4-app@latest my-agent
cd my-agent
npm install
npm test

A successful test result is the first useful checkpoint. The B4.run project has documented a clean-room installation in which the generated starter installed and its default fixture suite passed, with one opt-in test file skipped. That observation applied to the resolved version and date of that run. It is not a guarantee that every future @latest scaffold will produce identical output, test counts, or scripts.

Pinning versus following the latest generator

The convenience of @latest also means the generated project can change over time. B4.run is still before version 1.0, and the available evidence includes both a published 0.8.21 scaffold observation and a later 0.11.0 release. Treat version-specific commands, ports, and file layouts as observations rather than permanent interfaces.

For an evaluation, using @latest follows the official quickstart. For a repeatable team workflow, retain the generated lockfile, review package-version changes, and record the versions that passed your tests. Do not delete or regenerate the lockfile casually if reproducibility is important.

Understand the generated B4.run project

Before starting the server, inspect what the generator created. This is especially important when a tutorial and the installed package do not refer to exactly the same release. The generated package.json is the local source of truth for available npm scripts. Open it and review the scripts object rather than assuming every B4.run project exposes identical commands.

The framework uses file-system routing. A supported route entry is placed in an index.ts file under src/app/. Depending on the application, that entry can represent an agent, workflow, graph, or chain. Shared tools can be placed under src/tools/, and route-local tools can live in a route-specific tools/ directory. The route-local arrangement helps keep a route's implementation and available tools close together.

What B4.run generates or discovers

Project concern What the developer provides What B4.run handles
Route entry An agent, workflow, raw graph, or chain entry in a route's index.ts Route discovery and the runtime entry
Tools Shared tools or route-local TypeScript functions The tool set associated with a route, subject to runtime policy and constraints
Types Typed parameters, state schemas, and tool signatures Generated route, parameter, state, and tool declarations where definitions are discoverable
Testing Fixtures, tests, and application configuration A deterministic fixture-replay path, while live and recording modes remain explicit
Build output Application source and target-specific choices A runnable Node.js server, Dockerfile, and LangSmith graph artifacts from the default build
Infrastructure Runtime host, storage, secrets, provider access, and network policy B4.run does not provision or operate the hosting infrastructure

State and persistence expectations

B4.run's default SQLite-backed state can survive a development-server restart when the application root and its SQLite files persist. That does not mean every restart is stateless, and it does not make a development directory disposable. Identify generated database files before replacing the project directory, changing mounts, rebuilding a container, or automating cleanup.

Persistence also changes the security discussion. Threads, prompts, tool outputs, or application-specific state may remain on disk. Protect the host account, project directory, database files, logs, backups, and any external storage target according to the sensitivity of the application.

Provider credentials and live execution

The initial no-key path covers scaffolding and fixture-backed tests. Live use is provider-specific. The exact environment variable names and required credentials can vary with the generated starter and selected provider, so inspect the generated files before attempting a live call. If the server starts but a live agent invocation fails, distinguish that provider failure from an HTTP startup failure.

A running page does not prove that every agent capability is configured

The HTTP process may start successfully even when a live model provider, optional sandbox, external database, or route-specific integration is unavailable. Test the exact route and execution mode you intend to expose.

Start and verify the B4.run server locally

Terminal and browser views confirming that B4.run responds on its current localhost port.
The port reported by the running server should match the port used for the local browser test.

After the tests pass, inspect package.json and confirm that the generated project contains a dev script. For the documented published 0.8.21 scaffold, the supported development command was:

npm run dev

Run the command from the project root and keep the terminal open. Read the complete startup output. It should identify whether the process started successfully and which local address or port it selected. Do not create the Localtonet tunnel until this process remains running without a startup error.

Use a second terminal for verification

Leave the development process running and open another terminal. Use the exact URL printed by the current server. If it prints a loopback URL, request that URL from the same machine with a browser or an HTTP client. For example, if and only if your installed scaffold reports port 3000, a local request could be:

curl -i http://127.0.0.1:3000/

A browser can be used instead of curl. The important result is that the connection reaches the B4.run process. The precise HTTP status and response body depend on the generated release and requested route. A non-success status can still prove that an HTTP server answered, but it does not prove that the requested application route is correct. Verify a route that actually exists in the generated project.

A practical verification sequence

  1. Confirm that npm test finishes with the expected result.
  2. Start the development process and check that it does not exit.
  3. Record the host and port reported by that process.
  4. Request the reported local address from the same machine.
  5. Request an application route that exists in the generated scaffold.
  6. If applicable, separately test fixture-backed behavior and live-provider behavior.
  7. Only after those checks pass, configure the Localtonet HTTP tunnel.

This order keeps diagnosis straightforward. If a request fails before Localtonet is introduced, the fault is within the local runtime, route, dependency, provider, or host configuration. If local access works but public access fails, investigate the Localtonet target and tunnel lifecycle.

Confirm the correct B4.run port

Port selection is the most important version-sensitive detail in this workflow. The published 0.8.21 scaffold was observed starting its B4.run development server on port 3000. Separate source research templates have documented server and Workbench processes on ports 3002 and 3010. Those templates are distinct from the published package and must not be treated as proof that a newly generated @latest application uses either port.

Port observation Context How to use it safely
3000 Documented observation for the published 0.8.21 generated scaffold Use it only if the installed development server reports or confirms port 3000
3002 Server port documented for a separate source research template Do not copy it into a published-package setup unless the selected template actually uses it
3010 Workbench process port documented for that source research template Do not confuse a Workbench process with the B4.run server target
Any different reported port A future or differently configured scaffold may change its listener Use the port shown by the running process and confirmed through a local request

The reliable method is operational verification, not historical assumption. Start the project, read its output, inspect its generated configuration where necessary, and make a successful local request. Configure Localtonet with that same port.

Do not tunnel a guessed port

Pointing a tunnel at port 3000 merely because an earlier scaffold used it can produce a public endpoint that returns a connection error or reaches an unrelated local service. Confirm both the port number and the process listening on it.

Connect the verified B4.run server with Localtonet

Localtonet mapping an assigned public URL to the verified local B4.run port.
The Localtonet client port must match the port on which B4.run is currently listening.

Once the local HTTP service works, install and run our Localtonet client on the B4.run host or on a device that can reach that host. The client initiates an outbound connection to our relay, so the normal workflow does not require exposing a router port or assigning a public IP address to the development machine.

An HTTP tunnel is the appropriate family for a B4.run service that accepts HTTP requests. The tunnel target consists of a local IP address and the verified B4.run port. When the client and tunnel are running, Localtonet provides a public address that forwards traffic to that target.

1

Install and run the Localtonet client

Run the client on the B4.run machine or on another device with network reachability to the confirmed B4.run listener. Keep the B4.run server running during setup.

2

Authenticate or select the client device

Use the device-specific auth token associated with the client that will run the tunnel. Keep the token private and do not place it in source code, screenshots, shared terminal output, or the B4.run repository.

3

Select an available relay server

Choose a currently available server or region from the Localtonet product interface. Available values can vary, so obtain them from the current dashboard rather than copying a hardcoded server code from a tutorial.

4

Create an HTTP tunnel to the local B4.run service

Set the local target to the IP address and port that passed local verification. If the client runs on the same machine, use the appropriate local address for that listener. If it runs on another device, use a LAN address that the client device can actually reach.

5

Start the tunnel

Creating a tunnel does not start it. Use the Start button and confirm that the selected Localtonet client is connected and the tunnel is running.

6

Test the assigned public address

Open the assigned public HTTPS address from a separate browser or network and request a known B4.run route. Compare the result with the local request. Stop the tunnel when remote access is no longer required.

HTTP tunnels can use a random subdomain, a selected custom subdomain where supported, or a custom domain. These process types serve content at a public HTTPS address. Custom-domain DNS requirements can change and must be checked against the current documentation before configuring DNS records. Do not assume that every process type, region, or option is included in every plan.

For the current product workflow, consult our HTTP tunnel documentation. Use the documentation to confirm current dashboard labels and available selections, while keeping the local target based on the port you personally verified.

The tunnel depends on two running processes

The public endpoint works only while the selected Localtonet client is connected, the tunnel is started, and the B4.run server is accepting connections at the configured target. Restarting or stopping either process interrupts access.

Secure a remotely accessible AI agent server

A tunnel solves reachability. It does not decide whether an unknown user should be allowed to invoke an agent, consume model credits, read state, call tools, modify files, or approve an action. Apply security controls at the application and deployment boundaries before sharing the public URL.

Require appropriate authentication

Do not rely on an unlisted public URL as an access-control mechanism. Protect non-public routes with application-level authentication and authorization appropriate to the audience. Administrative, debugging, approval, and operational interfaces should receive stronger restrictions than intentionally public endpoints.

Limit agent tools and permissions

Review every tool available to the exposed route. A harmless greeting tool and a tool that executes commands, modifies files, sends messages, or accesses internal systems have different risk profiles. Apply least privilege, keep route-local tool sets focused, validate tool inputs, and preserve human approval for sensitive operations.

B4.run supports approval-oriented application patterns, but the exact controls are defined by the application. Verify that a sensitive action really pauses for approval and that the approved data cannot be replaced before execution.

Protect secrets and provider boundaries

Keep model keys and service credentials out of route responses, browser-delivered code, source control, fixtures, logs, and error pages. Use the secret-management method appropriate to the host. If a public request can cause a paid model call, consider authentication, quotas, request-size limits, provider budgets, and abuse monitoring.

Separate development from production

A development server is optimized for iteration and diagnostics. It may expose verbose errors, automatically rebuild code, or behave differently from the generated runtime artifact. For sustained public service, review the default build output and validate its runtime, storage, authentication, provider, and checkpointer behavior for the chosen deployment target.

Preserve local state carefully

If SQLite-backed state is in use, protect the files and understand their lifecycle. Back up required data before upgrades or migrations, avoid multiple incompatible processes writing the same database, and confirm file ownership when moving from an interactive shell to a service account or container.

Expose only the route and duration you need

Keep the tunnel stopped while configuring or repairing the application. Start it only after local verification, avoid exposing unrelated local ports, and stop or delete the tunnel when the remote-access requirement ends. A tunnel should support an intentional access policy, not replace one.

Operate, update, and validate the self-hosted service

For an interactive development session, the simplest operating model is to keep npm run dev in one terminal and the Localtonet client in another. That is useful during development but fragile for unattended use. Closing the terminal, rebooting the machine, stopping the client, or changing the listener can make the public endpoint unavailable.

Routine start sequence

  1. Start the B4.run process from the correct project directory.
  2. Wait for the startup output and confirm the current listener.
  3. Make a successful local request to a known route.
  4. Start or confirm the Localtonet client connection.
  5. Start the configured HTTP tunnel.
  6. Verify the public endpoint from outside the host.

Routine stop sequence

  1. Stop the Localtonet tunnel so new public requests no longer arrive.
  2. Allow in-progress work to finish where appropriate.
  3. Stop the B4.run process.
  4. Back up persistent state if the maintenance operation can affect it.
  5. Apply changes and repeat local verification before restoring remote access.

Updating the project

Do not rerun the latest generator over an existing application as an assumed upgrade procedure. Preserve source control history and the dependency lockfile, read the relevant migration or release information, update in a separate branch, and rerun tests. Validate route discovery, generated types, persistence, provider integration, and build output before starting the tunnel again.

If an update changes the development port, update the Localtonet target only after verifying the new listener locally. If it changes routes or response formats, test the public integration from a clean client rather than relying on a previously open browser session.

Building for a longer-lived deployment

The default B4.run build can emit a runnable Node.js server, Dockerfile, and LangSmith graph artifacts. However, the exact npm scripts and target-specific deployment steps must be read from the generated release. This guide does not invent a universal build or production-start command where the supplied evidence does not establish one.

Before replacing the development process, inspect the generated package.json and project instructions. Build the application using the script actually present, test the emitted server locally, determine its listener, and then point Localtonet at that verified process. Also confirm storage paths and environment variables in the final runtime environment.

Troubleshooting B4.run and Localtonet

Troubleshooting flow from the local B4.run process to the public Localtonet URL.
Check the local server and port before diagnosing the tunnel or public endpoint.

The scaffold command fails

Recheck node --version and confirm Node.js 24 or later. Confirm that npm is available and that the machine can access the package registry. If the generator created a partial directory, inspect it before retrying so that you do not accidentally mix files from separate runs.

npm install fails

Read the first meaningful npm error rather than only the final summary. Common categories include an incompatible runtime, network or registry access failure, filesystem permission problem, or dependency-resolution issue. Keep the lockfile and error output for diagnosis. Avoid using force flags as a default response because they can hide a compatibility problem.

npm test reports an opt-in test as skipped

A skipped opt-in test is not automatically an installation failure. The documented clean-room run of a generated starter passed its default fixture suite while one opt-in test file remained skipped. Read the current test output and generated project instructions to determine whether the skipped test requires live credentials or another explicit mode.

npm run dev is missing

Open the generated package.json and inspect its scripts. The documented command applies to the referenced scaffold, but @latest can move. Use only a startup script that the installed project actually defines. If the current scaffold has changed, follow its generated instructions rather than adding a guessed script.

The server starts on a different port

Use the port reported by the running server. Port 3000 is a version-specific observation, while 3002 and 3010 belong to a distinct source research template. Update local verification and the Localtonet tunnel target to the confirmed listener.

The local URL refuses the connection

Confirm that the development process is still running and that the request uses the correct host and port. Check the startup terminal for a crash, compilation error, or address-in-use message. If another program already owns the expected port, do not tunnel that port until you identify which process is listening.

The local root path returns 404

A 404 response can show that an HTTP server answered even though the requested route does not exist. Inspect the generated application routes and request a path the project defines. Do not use the existence of an HTTP response alone as proof that the intended agent is callable.

Local access works, but the public URL does not

Verify that the Localtonet client is connected, the correct device token was selected, and the HTTP tunnel was started. Then compare the tunnel's local target with the exact address and port used for the successful local test. Remember that creating a tunnel does not start it.

The Localtonet client is on a different machine

A loopback address such as 127.0.0.1 always refers to the machine on which the request originates. If the Localtonet client runs on another device, its loopback interface does not point to the B4.run host. The B4.run server must listen on an address reachable from that client, and the tunnel target must use the appropriate reachable local-network address. Make this change only within your network policy and host-firewall rules.

The public endpoint loads, but agent execution fails

Separate transport from application execution. If the public request reaches the same route as the local request, the tunnel may already be working. Check the B4.run process output for missing provider credentials, invalid model configuration, tool errors, unavailable storage, sandbox requirements, or an application exception.

The public endpoint stops after closing a terminal

The endpoint depends on both the B4.run process and the Localtonet client. Closing either interactive process can interrupt access. For unattended operation, use an operating-system or container process-management approach appropriate to your environment, but first validate the generated production runtime and persistence model. No universal service-manager configuration is provided here because paths, users, environment files, and startup commands vary.

Changes disappear or previous state remains unexpectedly

Code behavior can be affected by rebuilds or generated output, while application state may persist in SQLite files under the application root. Identify whether the problem concerns source code, generated artifacts, fixture data, or persistent state. Back up state before deleting files, and do not assume that restarting the development process resets the application.

Frequently asked questions

What Node.js version does B4.run require?

The documented B4.run quickstart requires Node.js 24 or later. Confirm the active runtime with node --version before scaffolding the project.

Does the initial B4.run installation require a model-provider API key?

The documented first activation uses a no-key path for scaffolding, dependency installation, and fixture-backed tests. Live execution is provider-specific and can require credentials. Inspect the generated project for the exact provider configuration instead of guessing environment-variable names.

Which port does B4.run use?

A published 0.8.21 scaffold was documented using port 3000 for npm run dev. Separate source research templates have used ports 3002 and 3010 for different processes. Because @latest can change, use the port reported and locally verified by your installed project.

Should I tunnel port 3000 immediately after installation?

No. Start the server, read its current listener, and make a successful local request first. Configure the Localtonet HTTP tunnel with the port that actually passed verification.

Does Localtonet require router port forwarding for B4.run?

No. Our client establishes an outbound connection to a Localtonet relay server, so this workflow does not require inbound router port forwarding, a public IP address, firewall port-forwarding changes, or VPN setup.

Does creating a Localtonet tunnel make it run automatically?

No. Tunnel creation and tunnel startup are separate lifecycle actions. After creating the HTTP tunnel, use the Start button. The selected Localtonet client must also remain connected.

Is a Localtonet URL enough to secure an AI agent?

No. The tunnel provides connectivity. The application owner must still implement appropriate authentication, authorization, least-privilege tools, input validation, secret protection, provider limits, and approval controls.

Can the Localtonet client run on a different device from B4.run?

Yes, if that device can reach the B4.run host and port over the local network. In that arrangement, do not use the Localtonet device's loopback address as the B4.run target. Use an appropriate reachable address and comply with local firewall and network policy.

Will B4.run state survive a development-server restart?

Default SQLite-backed state can survive a b4 dev restart when the application root and its SQLite files persist. Verify the actual storage configuration of your generated project before assuming that a restart resets or preserves particular data.

Is the development server suitable for a permanent public deployment?

Treat it as a development workflow unless you have explicitly validated it for your deployment. For longer-lived use, review the generated build target, runnable Node.js output, storage, authentication, provider configuration, checkpointer behavior, process supervision, and update strategy.

Connect your verified B4.run server with Localtonet

Once the generated application passes its tests and responds on a confirmed local port, create a Localtonet HTTP tunnel to make that specific service available through a public HTTPS address without inbound router port forwarding.

Get Started Free โ†’

Localtonet is a secure multi-protocol tunneling and proxy platform designed to expose localhost, devices, private services, and AI agents to the public internet supporting HTTP/HTTPS tunnels, TCP/UDP forwarding, mobile proxy infrastructure, file server publishing, latency-optimized game connectivity, and developer-ready AI agent endpoint exposure from a single unified control plane.

support