Skip to content

CLI commands

rndl routes

Print the deep-linkable route table of an Expo Router or React Navigation app, as an aligned table or JSON.

rndl routes scans your app and prints every deep-linkable route with its URL pattern and params. It is the foundation the other commands build on: validate cross-checks this table against your AASA file, open and interactive build URLs from it, and typegen turns it into types.

rndl routes                                          # auto-detects app/ then src/app/
rndl routes --json                                   # routes, API routes, layouts, diagnostics
rndl routes --app-dir src/app                        # explicit Expo Router directory
rndl routes --config src/navigation/linking.ts       # default or `linking` export
rndl routes --config src/navigation/linking.ts#named # a specific named export

Flags

FlagDescription
--jsonPrint the full scan result as JSON instead of the aligned table.
--app-dir <dir>Expo Router app directory. Defaults to app/, then src/app/.
--config <module[#export]>React Navigation linking module, with an optional named export after #.

--app-dir and --config are mutually exclusive: an app has one router.

Expo Router

The adapter walks your app directory and understands every file convention:

  • Dynamic segments ([id]) and catch-alls ([...slug]).
  • Route groups ((group)), including the array syntax ((a,b)) that expands one file into a route per group.
  • Platform-specific variants (.ios, .android, .native, .web).
  • _layout files (structural, not routes), index files (the parent path), and +not-found.
  • The special files +api (excluded and tagged as an API route), +html, +native-intent, and +middleware.

Conventions it does not recognize produce a warning, never a crash, so a new router release does not break your CI run.

React Navigation

The adapter imports your linking module under Node (TypeScript and ESM are handled for you) and walks config.screens recursively, honoring nested navigators, path, exact, alias, regex-constrained and optional params, wildcards, and prefixes. Params with a custom parse function are reported as unknown (custom parse), since their runtime type is not knowable from the config.

Because the module is executed outside the native runtime, keep the linking config in an isolated module that only exports plain data and parse/stringify functions (react-navigation imports are fine as import type):

// src/navigation/linking.ts
import type { LinkingOptions } from '@react-navigation/native';
 
export const linking = {
  prefixes: ['myapp://', 'https://example.com'],
  config: {
    screens: {
      Home: '',
      Article: { path: 'article/:slug', exact: true },
    },
  },
} satisfies LinkingOptions<Record<string, unknown>>;

If the import fails because the module pulls in native code, rndl prints an actionable error suggesting this isolated-module pattern.