Guide · ~5 min · AI Freelancers

Show, don't tell: demo your
AI agent without deploying

You built an AI agent for a client. It works on your machine. Now they need to see it, interact with it, poke at it. You don't need a cloud server for that. You need a URL.

Loom videos don't let clients click buttons

You finished the first version of an AI agent for a client. A chatbot, a data dashboard, an internal tool — whatever it is, it runs on your machine and it works. Now you need feedback.

You could record a Loom. Walk them through it, narrate your clicks, hope they can tell the difference between your demo and a mockup. But the client wants to try it. Type their own questions. Test edge cases. See what happens when they click something you didn't expect.

So now you need to deploy it somewhere. Spin up a Railway instance, or an EC2 box, or a Render service. Configure environment variables, database connections, API keys. Wait for the build. Debug why it works locally but not in the container. All for a 15-minute review that might end with "Actually, can we change the prompt?"

This is the tax on "show, don't tell." Showing a working prototype wins the contract — freelancers who do it report dramatically higher conversion rates than those who send proposals with slides. But the deployment overhead turns a quick demo into a half-day project.

Your laptop is already the server

Think about it. The app is running. The AI agent is responding. The database has test data. Your local machine is, right now, a fully functional server with the exact environment the client needs to see.

The only thing missing is a URL they can open in their browser.

That's what tunneling does. It creates a secure, encrypted connection from your machine to a relay server, and gives you a public HTTPS URL that routes traffic back to your local port. No DNS, no certificates, no firewall rules. The client opens a link, and they're interacting with the exact same thing you're looking at on your screen.

The key difference for client demos: you don't just want any URL. You want one that expires. One you can revoke the moment the demo is over. One that doesn't require the client to install anything, create an account, or click through a warning page. Just a link that works for exactly as long as you need it to.

Three commands, one URL

Here's the actual workflow. Your app is running locally on port 8080.

Your machine
localhost:8080
HLE tunnel
Encrypted
Client
Browser

Step 1: Expose your local app.

hle expose --service http://localhost:8080 --label demo

Your app is now live at https://demo-x7k.hle.world, protected by SSO. Only you can access it so far.

Step 2: Create a time-limited share link for your client.

hle share create demo-x7k --duration 1h --label "client review"

This generates a unique URL that works for one hour. No signup required. No SSO gate. The client clicks the link and they're in. When the hour is up, the link dies.

Step 3: Send the link. That's it.

Paste it in Slack, email it, drop it in the Upwork chat. The client opens it in any browser and interacts with your app directly. They see what you see. They click what you'd click.

When the demo is done, the link expires on its own. Or revoke it immediately:

hle share revoke demo-x7k 1
Need tighter control? Use --max-uses 1 to create a single-use link. The first person to click it gets access; the link is consumed. Useful when you want to make sure exactly one person sees it.

Nothing to install on the client side

This is the part that matters most for demos: the client does nothing.

No VPN client to install. No account to create. No app to download. No browser extension. No "click here to accept the risk." No instructions to follow. They get a link. They click it. They're using your app.

That's a bigger deal than it sounds. Every step you add between "here's the link" and "I'm using it" is a chance for the client to bail. Ask them to install a VPN client and half of them will say "let's just do a screenshare instead." Ask them to create an account and the email sits in their inbox for three days.

A share link has the same friction as a Google Doc link. The client already knows what to do with it. Click, use, done.

And because the link is time-limited, there's a natural urgency. A 24-hour link says "this is ready now, take a look while it's fresh." It doesn't linger in a bookmark folder forever. When it expires, it's gone — and the next iteration gets a fresh link.

The async feedback loop

Share links aren't just for live demos on a call. They're arguably more powerful for async reviews.

Create a 24-hour link, send it to the client with a note: "Here's the agent running with your data. Try it out whenever you have 15 minutes. The link expires tomorrow."

hle share create demo-x7k --duration 24h --label "async review - v2"

The client tests it at their own pace. No scheduling a call. No "are you free at 3pm?" back-and-forth. They interact with the real thing, form their own opinions, and come back with specific feedback instead of hypotheticals.

You can check if they've used the link:

hle share list demo-x7k

If the use count is still zero after 12 hours, nudge them. If it shows 4 uses, they've been thorough — expect detailed feedback. Either way, you have data instead of guessing whether they looked at it.

The whole thing in 60 seconds

Next time a client asks "Can I see it?", don't open AWS. Open a terminal.

# Your app is already running on localhost:8080

# Expose it
hle expose --service http://localhost:8080 --label demo

# Create a 1-hour share link
hle share create demo-x7k --duration 1h --label "client demo"

# Send the URL. Done.
# Revoke when finished:
hle share revoke demo-x7k 1

Your laptop is the staging server. The share link is the access control. The client sees the real thing, not a recording of it. And when the demo is over, the link disappears like it was never there.

Show, don't tell.