dumbtv
dumbtv takes the ads, screen tracking and update nags out of your Fire TV over ADB. No root, none of your apps touched, every step can be undone. Free and open source.
翻译准备中
Integrations for qURL — quantum-style URLs powered by LayerV. Resources are invisible until authorized observation.
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
Open-source integrations for qURL™ — Quantum URLs that make protected resources invisible by default.查看完整 README ↗Use qURL™ by LayerV to share localhost web apps, private APIs, and files through expiring access links. Share a development preview, an internal dashboard, or a document with a teammate or AI agent. This repository contains LayerV's CLI, Slack and Discord integrations, browser extensions for Gmail, and Microsoft Teams integration source.
For an app running on localhost, the CLI connects outward to LayerV without opening an inbound port. Publish the app, create a short-lived access link, and send that link to its recipient. The app must stay running, and its own sign-in still applies. Adding a link to an existing remote URL does not restrict any separate public route to that URL.
qURL uses OpenNHP to authorize access to protected resources. Start with the guide for the task you want to complete:
| Task | Guide |
|---|---|
| Share a local web app or API with a temporary link | qURL CLI quickstart |
| Share internal resources from a Slack channel | qURL for Slack |
| Send one-time file or location links in Discord | qURL Discord bot |
| Share files in Gmail through expiring links | Browser extension for Gmail |
| Build or submit the Microsoft Edge extension | Edge installation and release guide |
| Develop or deploy the Microsoft Teams integration | Teams integration source and deployment guide |
| Serve a private S3 static site through a connector | Private S3 origin image |
The CLI guide documents local publishing and sharing. Each integration guide lists its own setup requirements. Teams deployment is managed outside this repository; the presence of its source does not establish a public rollout.
Localhost quickstart · File sharing · Sharing comparison · Sharing questions · Product overview · Private links
For example, let a teammate review a preview running on your laptop without deploying a staging server. Your app stays on your machine; the CLI runs the Connector that carries access to it.
Install the CLI. On macOS with Homebrew:
brew install layervai/tap/qurl
qurl version
See the CLI setup guide for the authentication and deployment requirements of your installation, and other installation options for Linux or Windows.
Keep your existing app running on port 3000. To try a simple file-based preview, run this from a directory containing only files you intend to share:
python3 -m http.server 3000 --bind 127.0.0.1
In a second terminal, publish that local HTTP service:
qurl publish http://127.0.0.1:3000
Replace REPLACE_WITH_CRID with the resource identifier printed after the
route is ready. Create a link with a requested five-minute access window:
qurl share REPLACE_WITH_CRID --ttl 5m --session-duration 5m
Send the returned full qURL link privately. A browser recipient opens the link; your app's own login still applies. The service can shorten the requested lifetime. Keep the app, publishing host, and background daemon available while the recipient uses it.
The CRID identifies the resource; the minted link grants access. CRID-based link requests also depend on resource privacy and device grants. Read private CRIDs before handing a CRID to someone else's CLI or agent.
When the preview is over, stop serving it:
qurl stop REPLACE_WITH_CRID
stop pauses serving without retiring the resource. See the
command reference for restarting, deleting,
and managing individual links.
Choose a file workflow that matches where the file lives and how it should reach the recipient:
| Use case | Workflow |
|---|---|
| Review files in a local preview directory | Serve a dedicated directory with a local HTTP server, publish its root address with the CLI, and share the access link. Recipients can reach the files that server exposes. |
| Send an uploaded document from Gmail | Use the browser extension to upload selected files and insert expiring links into a compose draft. |
| Send separate file links to Discord recipients | Use /qurl send; the configured bot delivers recipient links by DM. |
| Let an AI agent share a selected PDF or image | Use the MCP upload tools, with their supported file types, transport modes, and expiry limits. |
A localhost file server and an uploaded file are different resource lifecycles. Local serving needs the host to remain available. Uploads use their configured file service. Opening or testing a single-use link can consume it; create a fresh recipient link when needed. Use each integration's guide for its actual revocation support and file-size limits.
A live preview, an internal API, and an uploaded report have different sharing requirements. Start with where the content should run and how the recipient should be authorized. qURL can connect these workflows through resource access links, while the publishing and file-upload components have their own setup and lifecycle.
| Approach | Where the app or content lives | Recipient access | Useful when |
|---|---|---|---|
| qURL local publishing | Your running app or HTTP file server, reached through the CLI's embedded Connector. | An issued access link, the resource's policy, and any app login. | A reviewer or agent needs temporary access to a particular local resource. |
| ngrok | Your running service behind an agent endpoint. | An endpoint URL with your configured Traffic Policy and app authentication. | You want a localhost endpoint for preview or integration testing. |
| Cloudflare Tunnel + Access | Your running origin connected through cloudflared. | The application's configured Access policies. | You want to manage application access through identities and groups. |
| Tailscale Serve | A service or files on a device in your tailnet. | Tailnet connectivity and access rules. | Your collaborators already use the private network. |
| S3 presigned URL | An object stored in an S3 bucket. | A signed URL for an operation, subject to its expiry and AWS policies. | Your artifact is in object storage and needs temporary download access. |
| Google Drive | A document or file stored in Drive. | Its configured viewer, commenter, editor, or link permissions. | Review and collaboration should continue through hosted document storage. |
| Vercel preview | A deployed application in a Preview environment. | A deployment URL and its configured protection. | Reviewers need a hosted build independent of your development machine. |
Both tools can connect an app on your machine to remote users without inbound port forwarding. The sharing workflow and access model are the useful points to compare:
| Question | qURL local sharing | ngrok's documented localhost workflow |
|---|---|---|
| What do I send? | An expiring access link for a published resource. | A public endpoint URL, which can be secured with Traffic Policy. |
| How is access controlled? | Resource identity, signed access grants, and the resource's link and session rules. The app can keep its own login. | Endpoint policies such as OAuth, OIDC, Basic Auth, and IP restrictions. |
| Does the origin need inbound port forwarding? | No; the Connector connects outbound. | No; the agent establishes an outbound tunnel. |
For private previews and temporary access to an internal app, qURL centers the workflow on issuing access to a resource. ngrok also documents public endpoint delivery, request inspection, and replay. Choose based on the access and testing workflow you need. See ngrok's localhost guide, ngrok security, and the LayerV sharing FAQ.
For a teammate reviewing the app currently running on your laptop, qURL's localhost quickstart publishes that service and then issues its access link. The app, host, and serving runtime must remain available. ngrok also connects to a running origin; using an outbound tunnel does not make either workflow a hosted deployment.
A Vercel Preview deployment gives reviewers a hosted version of the application. That is a useful choice when review should continue after your laptop goes offline or when you want to inspect a deployed build. It requires the application and environment to be configured for deployment. Use local sharing when the running development instance is the thing to review; use a hosted preview when a deployed version is the thing to review. Both need appropriate access controls.
Cloudflare Tunnel connects an origin outward without requiring a publicly routable origin IP. Cloudflare Access adds application policies, including identity-provider groups and session controls. For an internal dashboard managed through an organization's identity system, that application-access model can be a good fit. Outbound origin connectivity is shared by Cloudflare Tunnel and qURL; it is not a unique reason to choose qURL.
Tailscale Serve makes a service or files available within a tailnet, under its access rules. That fits collaborators who already have private-network connectivity. Tailscale Funnel has a different audience: it makes the configured service reachable from the public internet. Check which mode you are choosing before treating a Tailscale URL as private.
With qURL, the CLI publishes an individual resource and issues access under its resource, link, and session policies. A browser recipient uses the returned link without installing a qURL SDK. The full link is an access credential; sending it to a named person or setting a label does not authenticate that person's identity. Retain the app's login where identity matters. Choose based on whether your workflow needs resource access links, identity-managed application access, or existing private-network membership.
A qURL link to a local HTTP directory lets recipients read what that server exposes while the host remains available. It is useful for reviewing a current local output or static preview. Use a dedicated directory and the file-sharing workflow. For selected PDF or image uploads, the MCP tools use a configured upload service; its format, expiry, and revocation limits differ from local serving. The SDK's link-issuing calls alone do not upload a file.
An S3 presigned URL also provides temporary bearer access, scoped to an object and operation. For a download, the object must be in S3; your local machine does not serve that download. Its validity depends on the signing credentials and applicable policies. S3 checks expiry when a request starts, so a download already in progress can continue after URL expiry. Similarly, qURL link redemption and an admitted session have separate lifetimes. Expiring links are not an exclusive qURL capability, and expiry should not be described as erasing a downloaded copy.
Google Drive sharing is useful when the document belongs in hosted storage with viewer, commenter, or editor permissions. Eligible work or school accounts can also set access expiration. Choose Drive for that document-sharing workflow, an S3 URL for an object-storage download, or qURL for access to a running resource or a supported qURL upload integration. These choices put the content in different places; wrapping a separate public URL does not restrict its original access path.
No. In the local workflow, the app runs on your host and the CLI's embedded Connector carries access traffic. A sleeping laptop or stopped app cannot serve the preview.
Creating a qURL adds an access path. Close or restrict any separate public route if access should be available only through qURL.
Link expiry limits new redemption. An already admitted session has its own lifetime. The quickstart requests both limits; the service enforces them.
Use limits depend on the link and issuing workflow. A link is an access credential, so share it privately. It does not replace your app's login or prove a recipient's identity merely because you sent it to a named person.
apps/ Per-integration apps (released apps get independent release tracks)
slack/ Slack Secure Access Agent — /qurl slash commands (Go)
discord/ Discord app — one-time qURL links for files & locations (Node.js)
chrome-extension/ Shared Chrome and Edge extension source (MV3)
edge-extension/ Edge release metadata and store documents
cli/ CLI — publish, share, and manage qURL resources by CRID (Go)
teams/ Microsoft Teams Bot and OAuth integration (TypeScript)
origins/ Reusable origin images for qURL Connector-protected resources
s3-static-connector/ Private S3 static site origin behind qURL Connector
shared/ Shared Go libraries used by the Go apps
client/ qURL API client
auth/ API key helpers
observability/ OpenTelemetry setup
The qURL plugins live in their own repositories: layervai/claude-plugins for Claude Code and layervai/codex-plugins for OpenAI Codex. Each bundles the qURL agent skill; none needs an account.
Language SDKs and the qURL MCP server live in standalone repositories:
| Library | Install | Repo |
|---|---|---|
| Python SDK | pip install qurl-python | layervai/qurl-python |
| TypeScript SDK | npm install @layervai/qurl | layervai/qurl-typescript |
| Go SDK | go get github.com/layervai/qurl-go/qurl | layervai/qurl-go |
| MCP server | npx @layervai/qurl-mcp | layervai/qurl-mcp |
The Slack, Discord, and CLI apps connect to the qURL API:
https://api.layerv.ai, set via QURL_ENDPOINT. Required for Slack; the CLI and Discord use it by default.qurl login or QURL_API_KEY; qurl does not store the account key. See apps/cli/README.md.The Chrome and Edge builds use the same extension source and upload to a qURL file server; see the browser extension README and Edge release notes.
Onboarding is install-first: install the qURL Slack app, run /qurl setup <email>,
then an admin runs /qurl-admin protect to expose a resource in a channel and
anyone runs /qurl get to mint a one-time link.
See apps/slack/README.md for the full command reference and onboarding walkthrough, and apps/slack/docs/operating.md for deploying and operating the Secure Access Agent.
# Install pre-commit hooks
pip install pre-commit && pre-commit install
# Run all checks for the Go apps, shared/, and the repo itself (fmt, vet, lint, test)
make check
# The Node.js suites are opt-in — run the one matching your change
# (make check-node runs all five, but that is five npm installs)
make check-discord
# Run all tests
go test ./...
# Run tests for a specific app
go test ./apps/slack/...
# Build Slack Lambda
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o bootstrap ./apps/slack/cmd/
See CONTRIBUTING.md for development workflow, PR requirements, and code conventions.
This repo uses Release Please in monorepo mode.
Each released app has an independent version track. A track is earned by cutting a semver
version stream that something downstream pins to — not by merely publishing an artifact.
origins/s3-static-connector/ ships a container image but tags it only :main and :<sha>, and
shared/ and apps/teams/ ship nothing, so neither has a track:
feat(slack): add thread replies → slack-v0.2.0v0.2.0, not cli-v0.2.0) so OSS
GoReleaser can parse the tag — see the header of
.github/workflows/release-please.yml before "normalizing" itshared/ changes ship with each
app's next releaseCHANGELOG.md once its first release landsEach app's workflow runs on every PR. A changes detector job inside it decides whether that
app's quality gates actually execute, and an always-reporting aggregate check — slack / required,
discord / required, chrome-extension / required, edge-extension / required,
teams / required, cli / required, s3-static-connector / required, e2e / required,
shared / required — summarizes the result. Branch protection requires those aggregates, never
the gates themselves. The full required-context set, and the rules for changing it, live in
CONTRIBUTING.md — keep this list in step with that one.
Path filtering deliberately lives in the detector rather than in on: paths:: a workflow skipped
by a trigger-level path filter never reports its checks at all, so a required aggregate would
block every PR that happens not to touch that app. The detector's filter is the source of truth
for which paths need validation, and shared-test.yml runs all Go app tests when shared/
is modified.
That pattern is itself under test. internal/ciworkflows reads every file in
.github/workflows and fails when a workflow grows a required aggregate with no registered
spec, leaves a quality gate out of required.needs, ships a verifier that treats a skipped gate
as a pass, or makes the contract check conditional. It also records every pull-request workflow's
intended branches: filter, so one recorded as deliberately narrow fails the moment it reports a
required context — including the nine aggregates, whose recorded filter is weighed against the
documented contexts rather than only against itself, so narrowing one cannot be laundered by
editing requiredWorkflowSpecs to match. This is the paths filter's trap inverted: a
workflow filtered off PRs stacked on a feature branch never registers its checks at all, and
protection guards only main, so the stacked PR reads green having run none of them
(#1183, #1185). Deleting the merged base does not recover the run: GitHub retargets the PR onto
main, but a base change arrives as the edited activity type, which no branch-filtered workflow
here takes, so the retarget re-runs nothing. The PR stalls on the check that never registered until
its next push (#1219). The package's own check — Workflow Contract — is unfiltered and reports
on every PR, because a check behind a paths filter cannot police the paths filters (#1081).
MIT — Copyright (c) 2025-present LayerV, Inc.