Straight to the screen. On the record.
One command sets up Strait deep links in your app. Every link open and install is then recorded in your Strait dashboard.
Docs · Platform status · Talk to the Strait team
@straitlink/cli
npx @straitlink/cli init # set up deep links in your app
npx @straitlink/cli doctor --host acme.strait.link # check the link host lists your app
npx @straitlink/cli links create summer https://acme.com/s # create a link (secret key in env)
npx @straitlink/cli test # key, engine and link domain: pass/fail (secret key in env)
npx @straitlink/cli events add purchase # print the code that tracks an eventstrait init sets up Strait deep links in a React Native, Expo, Flutter or Android (Kotlin) app:
-
Detects the app from its files (
package.json,app.json,pubspec.yaml, Gradle files). Nothing is run. -
Takes your publishable key and link host as flags, or asks for them in a terminal. A secret key (
st_live_…) is refused, because it must never ship in an app. -
Writes the integration file, with your key, host and an
onLinkhandler:App File written React Native links.ts(orlinks.js)Expo links.ts, plusapp/+native-intent.tsxwith Expo Router (src/links.tsandsrc/app/+native-intent.tsxwhen your routes live insrc/app)Flutter lib/links.dartAndroid app/src/main/java/<package>/StraitLinks.kt -
Prints the remaining steps for your app: the install command, the AndroidManifest intent filters (or the
app.jsonblock for Expo), the iPhone Associated Domains entry, what to fill in under Dashboard → Apps & stores, and thecurlchecks forassetlinks.jsonandapple-app-site-association. Steps the project already has, such as the intent filters, are marked[already done].
It edits one existing file, and only when needed: in a Flutter or Android (Kotlin) app it adds <uses-permission android:name="android.permission.INTERNET" /> to AndroidManifest.xml if it isn't there. Flutter's own template only has it in debug builds, so without it a release build can't reach Strait and no link or install is matched. Everything else it prints for you to add. It never overwrites an earlier integration file unless you pass --force, and --dry-run shows the manifest line without writing it.
Run it in your app's folder. Node 18.17 or newer; nothing to install first.
npx @straitlink/cli init # asks for the key and host
npx @straitlink/cli init --key st_pub_live_… --host acme.strait.link
npx @straitlink/cli init ../my-app --dry-run # show the files and steps, write nothingFrom a checkout of this repo: node bin/strait.mjs init ../my-app, or npm link && strait init.
| Option | |
|---|---|
--key |
Publishable key (Dashboard → Get started). Env: STRAIT_PUBLISHABLE_KEY |
--host |
Link domain, e.g. acme.strait.link. A pasted link works too. Env: STRAIT_LINK_HOST |
--scheme |
Custom scheme: the one you typed in Dashboard → Apps & stores. Taken from app.json, or guessed from the package name (com.acme.shop → acmeshop); a guess is marked "(guessed from …)" in the output |
--framework |
react-native, expo, flutter or android, to skip detection |
--dry-run |
Print the files and steps; write nothing |
--force |
Replace an existing integration file |
--yes, -y |
Never prompt. Exits 2 if something is missing (for CI and agents) |
Exit codes: 0 done, 2 usage problem (message on stderr), 1 unexpected error.
npx @straitlink/cli doctor --host acme.strait.link --android com.acme.shop --ios com.acme.shopRuns the same checks, with the same finding ids and wording, as doctor() in the Strait SDKs (React Native, Flutter, iOS, Android and Unity; contract B23, the shared cases in test/doctor-vectors.json). It fetches https://<host>/.well-known/assetlinks.json and apple-app-site-association once each and tells you whether your package, bundle ID and (with --cert) signing certificate are listed, with the fix for each problem:
Android (assetlinks.json)
error app.missing acme.strait.link doesn't list com.acme.shop
Fix: Add com.acme.shop in Dashboard → Apps & stores (listed now: com.acme.app).
| Option | |
|---|---|
--host |
Your link domain. Env: STRAIT_LINK_HOST |
--android <package> / --ios <bundleId> |
The app to look for. With neither, both files are checked and the apps they list are shown |
--cert <sha256> |
Android signing certificate fingerprint, any format; repeat for debug, release and Play App Signing |
--key |
Also check the publishable key. Env: STRAIT_PUBLISHABLE_KEY. Left out, the key check is skipped |
--json |
The reports as JSON, for CI and agents |
Exit codes: 0 no errors (warnings allowed), 1 a check failed, 2 usage problem. What a terminal can't see (intent filters, the Associated Domains entitlement) is checked by doctor() inside a debug build and by the free tools.
export STRAIT_SECRET_KEY=st_live_… # Dashboard → Settings → Secret keys
npx @straitlink/cli links create summer https://acme.com/summer --campaign sale --tag email
npx @straitlink/cli links list --status active --limit 20
npx @straitlink/cli links qr summer --size 512 # writes summer.png
npx @straitlink/cli links qr summer --format svg --out summer.svgThese call the public API (POST /v1/links, GET /v1/links, GET /v1/links/{slug}/qr) with a secret key from STRAIT_SECRET_KEY or --secret-key (the environment is better: flags stay in your shell history). The key is never printed, not even inside an API error. A publishable key is refused here. --api-url (env STRAIT_API_URL) points at another engine and must be https. --json prints the API answer as is. A QR file is never overwritten without --force.
Exit codes: 0 done, 1 the API said no or can't be reached (its message on stderr), 2 usage problem.
export STRAIT_SECRET_KEY=st_live_… # Dashboard → Settings → Secret keys
npx @straitlink/cli testStrait test
pass Engine https://strait.link answers (version ddca50a)
pass Key valid live key st_live_3f9a… for workspace "Acme"
pass Link domain acme.strait.link (plan starter)
pass iPhone acme.strait.link lists TEAM123.com.acme.shop
pass Android acme.strait.link lists com.acme.shop
All checks passed.
Your app's own setup (intent filters, Associated Domains): strait doctor --android <package> --ios <bundleId>.
One read-only pass: the engine answers (GET /healthz), the secret key is valid and which workspace it belongs to, test or live (GET /v1/workspace), and the workspace's link domain serves apple-app-site-association and assetlinks.json listing your apps (the same checks as strait doctor). A failed check prints its fix; checks that need it are skipped. Exit 1 when any check fails, 2 for a missing or wrong kind of key, so it can gate a CI job. --json prints { ok, workspace, checks }. Same key rules as strait links: never printed, publishable keys refused.
npx @straitlink/cli events add purchase # platform detected from the project files
npx @straitlink/cli events add sign_up --platform ios # react-native | flutter | ios | android | web
npx @straitlink/cli events add purchase ./mobile # [dir]: the app folder, default the current onePrints ready-to-paste code with each SDK's own call: trackEvent in React Native (and Expo), Flutter, iOS and Android, using the client strait init wrote; on the web, reportWebOpen on page load plus trackEvent from @straitlink/web. The platform is detected from package.json, pubspec.yaml, Gradle files, an .xcodeproj or Package.swift. Nothing is written. Event names are 1-64 letters, numbers, spaces and _ . : -.
Every install line the CLI prints comes from INSTALL in src/install.mjs (source + githubOwner). It mirrors install in site/site.config.json and INSTALL in dashboard/src/lib/install.ts, and test/install.test.mjs fails if they drift while the repos sit side by side. Moving the SDK repos to an organisation means changing githubOwner. Publishing to npm, pub.dev and Maven Central means changing source to "registry".
npm test # node:test, no dependencies
node scripts/time-to-first-link.mjs # see docs/TIME-TO-FIRST-LINK.mdFixture apps live in test/fixtures/ (bare React Native, Expo with and without Expo Router, Flutter, Kotlin, and a folder with no app).
- Docs: straitlink.in/docs/ · platform status · troubleshooting
- Talk to the Strait team: support@straitlink.in (replies within 1 working day, IST) or call +91 81218 61890.
- Bugs and feature requests: open an issue on this repo.
- Security: never in a public issue. Write to security@straitlink.in.
MIT. See LICENSE.