Turn a local file, directory, or service into a URL with zero configuration.
$ npx giveurl ./report.html
https://laptop.example.ts.net/giveurl/20260802T154500Z-a1b2c3d4e5f60708/artifact.htmlgiveurl inspects providers already installed and authenticated on the current machine. Tailscale and GitHub Gists work today; Cloudflare remains visible in discovery behind the same provider interface for a future transport.
Agents and their harnesses often run on different machines. A screenshot, Markdown handoff, HTML lesson, or localhost preview should cross that boundary without choosing ports, editing configuration, or uploading private material to an arbitrary third party.
With Tailscale, each share gets a unique HTTPS route on the source machine. Files and directories are served from an OS-assigned loopback port behind Tailscale Serve, so concurrent machines and agents do not contend for ports. Access remains governed by the tailnet and its ACLs.
- Node.js 20 or newer
- At least one ready provider:
- Tailscale installed, signed in, and running with MagicDNS and HTTPS available
- GitHub CLI installed and authenticated to
github.comwith thegistscope
No runtime npm dependencies are installed. Standard gh auth login authentication includes the Gist scope.
Share a file, a directory with relative assets, or a localhost service:
npx giveurl screenshot.png
npx giveurl ./lesson
npx giveurl http://127.0.0.1:3000
npx giveurl 3000The URL is the only value written to stdout. Human diagnostics and the cleanup command go to stderr, so command substitution stays clean:
url="$(npx giveurl -- ./report.md)"
curl -fL "$url"For agents and scripts, use stable JSON:
npx giveurl ./report.md --json
npx giveurl providers --json
npx giveurl status --jsonPreview a change without creating a server, Tailscale route, or Gist:
npx giveurl ./site --dry-runTailscale shares remain available while the source machine and local backend are running; GitHub Gists remain hosted until deleted. Stop the share represented by a particular URL:
npx giveurl stop https://laptop.example.ts.net/giveurl/ID/artifact.html$ npx giveurl providers
PROVIDER INSTALLED AUTHENTICATED SUPPORT DETAIL
Tailscale yes yes ready laptop.example.ts.net
GitHub Gists yes yes ready authenticated; UTF-8 text files ready
Cloudflare no no planned not installedProvider selection defaults to auto, preferring Tailscale when it is ready and falling back to GitHub for compatible files. The provider name can be pinned for reproducible automation:
npx giveurl ./report.html --provider tailscale
npx giveurl ./report.md --provider githubCurrent provider status:
| Provider | Discovery | Publishing |
|---|---|---|
| Tailscale | tailscale status --json |
Files, directories, and localhost services |
| GitHub Gists | gh auth status |
UTF-8 text files up to 10 MB |
| Cloudflare | wrangler whoami |
Planned |
The GitHub provider creates a secret Gist and prints the direct raw file URL rather than the Gist HTML page:
npx giveurl ./report.md --provider githubGitHub Gists support one UTF-8 text file per share. Binary files, directories, and localhost services require Tailscale. giveurl status recognizes only Gists carrying its internal description marker, and giveurl stop <url> verifies the account, marker, and unmodified page or raw URL before deleting the Gist.
giveurl does not make Tailscale shares public to the internet. Any tailnet peer permitted by your Tailscale policy may be able to read the shared route, so publish the narrowest useful file or directory. Filesystem shares start a detached loopback server and persist across terminal sessions until giveurl stop is run or the source machine restarts.
A secret GitHub Gist is unlisted, not private: anyone who receives its URL can read it. GitHub hosts the file after the source machine goes offline, and the share remains available until giveurl stop deletes the Gist or it is deleted through GitHub.
Existing Tailscale Serve handlers are preserved. Cleanup turns off the exact /giveurl/<id> route and its matching loopback process rather than resetting the machine's Serve configuration. GitHub cleanup deletes only a Gist that belongs to the authenticated account and carries the giveurl marker.
The small giveurl skill in skills/giveurl/SKILL.md teaches an agent when to publish, verify, consume, and stop a share. Install or link it using the skill mechanism supported by your agent harness.
Install it globally with the Skills CLI:
npx skills add https://github.com/adinvadim/giveurl --skill giveurl -gnpm test
npm pack --dry-run
npm run smoke:tailscale -- --receiver root@runner
# Or use regular SSH over a Tailscale IP:
npm run smoke:tailscale -- --receiver-ssh mini@100.64.0.1 --identity ~/.ssh/id_ed25519
# If the receiver intentionally has MagicDNS disabled:
npm run smoke:tailscale -- --receiver root@runner --resolve-sourceThe live smoke test publishes every supported MIME type, directories, concurrent shares, HTTP ports, localhost URLs, and an https+insecure service. With --receiver, every artifact is fetched from another tailnet machine over Tailscale SSH; --receiver-ssh supports regular SSH over a Tailscale IP. It also verifies exact bytes, content types, Range requests, nested-route cleanup, and restoration of the previous Serve configuration. --resolve-source preserves TLS hostname validation while routing directly to the source Tailscale IP, which is useful only when the receiver has MagicDNS intentionally disabled.
The CLI uses only Node.js built-ins. Provider-specific behavior lives under src/providers/ so new transports do not complicate the default command.