Give an AI agent access to a local app
Checked against the qURL™ CLI 3.4.1 source and documentation on October 8, 2026. Link and session behaviour is tested separately.
Content updated October 18, 2026. The verification date above records the original review; later behaviour checks are dated in the guide.
How do I let an AI agent share or use an app running on my machine?
Give your coding agent the qURL skill. It checks policy support, publishes privately, and gives you an address to send. Choose access rules and recipient emails for invitations. Recipients verify email in their own browser; never ask for their verification codes. If the deployment cannot support the policy, the app stays private. For another agent, ask for a one-time access link and open it with the qURL Go SDK.
What you need
- A coding agent that runs shell commands on the machine where the app runs (Claude Code, Codex, Cursor, and similar)
- An app running on this machine
- For an agent that opens a link in code: Go 1.26.6 or later
- No account or API key
Steps
Give the agent the qURL skill
For Claude Code, save the skill to your personal skills folder. If Claude Code was already running and this created the folder, run /reload-skills. Other agents read the file from its URL; the prompt in the next step points them there.
mkdir -p ~/.claude/skills/qurl && curl -fsSL https://layerv.ai/skills/qurl/SKILL.md -o ~/.claude/skills/qurl/SKILL.mdAsk it to share the app
The agent finds the running app (or asks which one), installs the CLI if needed, publishes the app as a private resource, and gives you an address to send. The agent applies the private access rules you choose. For named recipients, give it their email addresses so it can send invitations. Recipients verify their email in the browser and save a passkey; they never send you their email verification code. The agent checks policy support before sharing and keeps the app private if the deployment cannot support it. To let one person in at once, ask it for a one-time access link; that link is a secret.
Read https://layerv.ai/skills/qurl/SKILL.md and use qURL to share the app I'm running locally.For another agent, send it a link to open in code
Ask your coding agent for a one-time access link, and send it to the other agent. An agent with a browser tool can open the link the way a person does. In code, open it with the qURL Go SDK (github.com/layervai/qurl-go/qurl). It needs no LayerV credentials, but opening uses the link’s one opening, so don’t open it first. The SDK connects over UDP port 443 by default. Fetching the link with curl returns the opener page, not your app.
handle, err := qurl.EnterPortal(ctx, link) if err != nil { return err } req, err := http.NewRequestWithContext(ctx, http.MethodGet, handle.ResourceURL, nil) if err != nil { return err } if err := handle.AuthorizeContentRequest(req); err != nil { return err } resp, err := (&http.Client{CheckRedirect: handle.CheckContentRedirect}).Do(req) if err != nil { return err } defer resp.Body.Close()
What the recipient sees
A person opens the address in a browser and sees who published the app, marked Not verified. Today LayerV has verified only its own account, so every other publisher is shown as not verified. Recipients of a private invitation verify email in their own browser and save a passkey; their email verification code stays in that flow. For an existing legacy resource only, they ask for access and pass on a legacy code through a trusted channel. A person with a one-time link lands on your app directly. An agent that opens that link with the SDK gets your app’s URL and calls AuthorizeContentRequest on each request to it until the session ends, 1 hour by default. Either way, the session admits the network address the opener connects from.
Troubleshooting
| If you see | Do this |
|---|---|
| The agent got an HTML page titled “qURL - Private Links That Expire” instead of the app | It fetched the access link over plain HTTP. The credential is in the URL fragment, which HTTP clients never send. Open the link with the SDK, or use qurl get <CRID> --file if you own the resource. |
| EnterPortal times out | The SDK opens links over UDP port 443, and some networks block outbound UDP. Run the agent on a network that allows it; the SDK’s opening-links doc describes a relay-only setup. |
| A retried EnterPortal call is denied | The first attempt used the link’s one opening. Ask for a new link. |
| For an existing legacy resource, the agent cannot turn on access requests, or publishes with no Access: line in the output | The CLI is older than 3.4.1. Ask the agent to update it; the skill’s install step always installs the latest release. qurl --version should then print 3.4.1 or later. |
| The private-policy commands are unavailable or consumer access is disabled | Ask the agent to follow the access-policy support check in the qURL skill. It updates an older CLI when needed. If the deployment cannot support the requested policy, stop sharing and keep the app private; do not fall back to legacy access requests. |
| qurl publish says the local app is not accepting TCP connections | Start the app first and check that curl works on the same address. qurl publish connects to localhost as 127.0.0.1, so if your app listens only on IPv6 (on macOS or Linux, lsof -iTCP -sTCP:LISTEN -nP shows [::1]), publish 'http://[::1]:PORT' instead. Keep the quotes: zsh treats the brackets as a pattern. |
| The recipient sees “Access link invalid” | The link was already used or has expired. Run qurl share again and send the new link. |
| The recipient sees “Resource not found” | The resource was deleted after the link was made. Publish the app again, then run qurl share and send the new link. |
| publish rejects http://127.0.0.1 with “only HTTPS URLs are allowed”, or asks you to log in | You have a CLI older than 3.0. On macOS run brew update, then brew upgrade qurl; elsewhere install the latest release again. After updating, qurl --version should print 3.4.1 or later. |
| publish prints no Access: line, or the Access: line says public and you did not ask for public | With no Access: line, the CLI is older than 3.4.1: on macOS run brew update, then brew upgrade qurl; elsewhere install the latest release again. A resource that an older CLI published is public unless you published it with --private, and anyone who has the CRID of a public resource can open it. To make a public resource private, run qurl delete <CRID> and publish again with qurl 3.4.1 or later. The new resource is private and has a new CRID. |
| publish says this Linux session “can’t reach a systemd user manager” | You are in a container or sandbox without a user service manager. Run qurl publish with --foreground; sharing lasts as long as that process runs. |
| publish says “Quota Exceeded” with “protected resource limit reached”, or “Your qURL account has reached a plan limit” | You can see this without an account: a device with no account can keep up to 3 active resources, with links that last up to 24 hours. Run qurl list --status active, then qurl delete <CRID> for any you no longer need (it asks you to confirm; --yes skips that). qurl stop keeps the resource, so it does not free a slot. |
Frequently Asked Questions
Does the agent need a LayerV account?
No. Publishing from the CLI needs no account, and opening a received link with the SDK needs no LayerV credentials. Without an account the publishing machine can keep up to 3 active resources, with links that last up to 24 hours.
Can the agent open the link from TypeScript or Python?
Not without extra setup. The TypeScript and Python enterPortal calls go through the LayerV API and need an API key. The Node opener in @layervai/qurl/node needs no key but needs a QURL_DEPLOYMENT trust file. The Go SDK has production settings built in.
Will the agent send the address or a link to other people?
It gives the address or link to you, and you decide who receives it. It sends invitation emails only to recipients you authorize. For legacy resources, it approves only a code you pass on, never the name on a request.
Who else can reach my app while the link is open?
Opening the link admits the network address it was opened from for the session, which lasts 1 hour by default. Other devices that share that public IP address, such as people on the same office or café network or VPN, can reach the app until the session ends. By default a link admits whoever opens it; access rules set through the API, such as IP allow and deny lists, can restrict that. Keep your app’s own sign-in for anything sensitive.