Tangly v0.2 ships richer code blocks, page chrome, and more — see what's new

CLI

Every Tangly command (init, dev, build, check, migrate, eject, add, preview) with flags, defaults, and examples.

~ 6 min read

The tangly binary is the primary surface for working on Tangly projects. Eight commands cover scaffolding, dev, build, validation, migration, ejection, and content scaffolding.

bash
tangly --help

Install

npm install --save-dev tangly
yarn add --dev tangly
pnpm add --save-dev tangly
bun add --dev tangly

Or install globally:

bash
bun add -g tangly

Staying up to date

In an interactive terminal, tangly checks npm at most once every 12 hours and prints a one-line notice when a newer version is published:

⚠ Update available: tangly 0.1.5 → 0.1.6
  Upgrade: `npm i -g tangly@latest` (or run `npx tangly` for the local copy)

The check is fail-silent (offline or slow registry: no notice) and never runs in CI or piped output. Opt out with TANGLY_NO_UPDATE_CHECK=1 or NO_UPDATE_NOTIFIER=1.

Every command also stamps the running version into its output, and tangly --version prints it directly, so you can always confirm which binary ran.

Common flags

Every command accepts these:

FlagDefaultDescription
--root <dir>.Project root
--config <path>docs.jsonPath to docs.json relative to --root

The other flags vary per command.

init

Scaffold a new Tangly project. Two paths: pick a built-in template (interactive), or hand --from <dir> to ingest an existing folder of .md/.mdx files.

bash
tangly init [dir] [--from <dir>] [--template <name>] [--name <name>]
Arg / flagTypeDefaultDescription
dirpositional.Target directory
--fromstringPath to existing markdown folder. Walks the tree (folders → groups), synthesizes docs.json. Idempotent: re-runs merge new files into existing nav.
--templatestringstarterTemplate name. Skip the interactive prompt.
--namestringProject name. Skip the interactive prompt.

Examples

bash
tangly init my-docs

tangly init . --from ../legacy-docs

tangly init --template starter --name "My Docs" my-docs

dev

Start the dev server with HMR.

bash
tangly dev [--port 4321] [--host] [--no-open] [--debug] [--tunnel]
FlagTypeDefaultDescription
--portstring4321Port
--hostbooleanfalseBind 0.0.0.0 so other devices on the LAN can reach the dev server. Without this, only localhost/127.0.0.1 works.
--openbooleantrueOpen browser on start. Use --no-open to suppress.
--debugbooleanfalseVerbose Vite/Astro logging
--tunnelbooleanfalseExpose via a cloudflared quick tunnel. Requires cloudflared on PATH.

The dev server pre-validates your docs.json manifest before launching Astro. Schema errors surface immediately, not buried in a stack trace.

bash
tangly dev --port 8080 --host --no-open

build

Production build to dist/.

bash
tangly build [--out ./dist] [--adapter <auto>] [--base /] [--site-url <url>] [--env <env>] [--analyze]
FlagTypeDefaultDescription
--outstring./distOutput directory
--adaptervercel | cloudflare | node | static(auto)Auto-detected from project files: vercel.json → vercel, wrangler.toml/wrangler.jsonc → cloudflare, Dockerfile → node, else static.
--basestring/Subpath. Pass --base /docs to deploy under /docs. Rewrites every internal link, asset URL, sitemap entry, llms.txt URL, and Pagefind result.
--site-urlstringdocs.json siteUrlAbsolute deploy URL. Overrides siteUrl for canonical, og:image, sitemap, and robots.txt. Also reads TANGLY_SITE_URL.
--envproduction | preview(auto)Deploy environment. preview emits robots: noindex and points canonical at the production domain. Also reads TANGLY_ENV.
--analyzebooleanfalseWrite a build-size report to dist/_tangly/.

Site URL & environments

Canonical tags and og:image need an absolute URL, but the deploy host varies (production, staging, PR previews). Tangly resolves it per build, highest priority first:

  1. --site-url / TANGLY_SITE_URL
  2. Platform auto-detect — Vercel, Netlify, and Cloudflare Pages deploy URLs are read automatically
  3. siteUrl in docs.json

og:image points at the current deploy (so the image resolves on a preview); canonical points at the production domain (so previews never compete in search). Non-production deploys (--env preview, or an auto-detected preview/branch context) also get <meta name="robots" content="noindex, nofollow">.

bash
# Staging deploy: cards resolve at staging, canonical + sitemap stay on prod, noindex
tangly build --site-url https://staging.docs.example.com --env preview

On Vercel/Netlify this is zero-config — PR previews self-reference and go noindex automatically. Cloudflare Pages exposes no production signal, so set --env preview (or TANGLY_ENV=preview) on preview branches. In tangly dev, canonical/og:image use the live request origin so you can preview cards locally.

Output

dist/
├── index.html              redirects to first nav page
├── introduction/index.html
├── guides/<slug>/index.html
├── images/                 copied from project root
├── logo/
├── og/<slug>.png           generated social cards
├── sitemap.xml
├── robots.txt
├── llms.txt
└── llms-full.txt

The build also generates a per-page <slug>.md file (markdown, no MDX) so AI agents can fetch a clean text version of any page.

Examples

bash
tangly build

tangly build --adapter cloudflare --base /docs

tangly build --analyze

check

Validate config, links, frontmatter, and MDX.

bash
tangly check [--strict] [--no-links] [--json] [--include-drafts]
FlagTypeDefaultDescription
--strictbooleanfalseWarnings become errors (non-zero exit). Use this in CI.
--no-linksbooleanfalseSkip link checking
--jsonbooleanfalseMachine-readable output
--include-draftsbooleanfalseInclude draft: true pages in checks
bash
tangly check

tangly check --strict

tangly check --json | jq '.errors'

Exit code is 0 when there are no errors (or no errors+warnings under --strict), 1 otherwise.

MDX validation

Every page is parsed with the same MDX syntax configuration the build uses (the remark plugins that affect what parses as a JSX expression), so check passing predicts build passing for this class of failure:

  • Syntax errors (unclosed JSX tags, malformed expressions, bad import/export) are reported with file:line:column.
  • Unbound expression identifiers are flagged before they become prerender ReferenceErrors. The classic case is a literal placeholder in prose — {search_term_string} is valid MDX, compiles, and only explodes at render time:
✗ rules/schema/website-search.mdx:5:6 — ReferenceError at build: `search_term_string` is not defined
      hint: MDX treats {…} as a JSX expression — wrap literal placeholders in backticks

The fix is usually to wrap the placeholder in backticks: `{search_term_string}`. Identifiers bound by the file’s import/export statements, expression-local declarations and arrow params, MDX-provided names (props, frontmatter, components), and JS globals are all recognized. Files under /snippets are never scanned — reusable snippets legitimately take bare {props}-style variables from the importing page.

migrate

Migrate a project to Tangly. Two paths:

  • Legacy: project has mint.json → full conversion via convertMintToDocs.
  • Modern: project has docs.json → validate + update the $schema URL.
bash
tangly migrate [--yes] [--keep-source]
FlagTypeDefaultDescription
--yesbooleanfalseSkip confirmation prompts
--keep-sourcebooleanfalseKeep mint.json after legacy migration. Without this flag, mint.json is renamed to mint.json.bak (or .bak.1, .bak.2, …).

Examples

bash
tangly migrate

tangly migrate --yes

tangly migrate --keep-source

If your theme: value isn’t a Tangly theme (a Mintlify alias like aspen or maple), migrate rewrites it to tang — the schema maps every alias to tang at parse time anyway, so the rewrite only makes the file say what it does. The notice lists the other Tangly themes if you’d rather pick one.

When docs.json has no siteUrl, migrate prompts for your production URL (used for canonical links and social cards). Press Enter to skip; --yes skips the prompt entirely.

eject

Materialize the synthesized Astro project into your repo. Irreversible.

bash
tangly eject [--out ./.tangly] [--yes]
FlagTypeDefaultDescription
--outstring./.tanglyEject destination
--yesbooleanfalseSkip confirmation

After eject:

  • ./.tangly/ contains a real Astro project (astro.config.mjs, src/, etc.)
  • package.json adds raw Astro deps (astro, @astrojs/mdx, tailwindcss, …) and rewrites dev/build/preview scripts to call astro directly. The tangly package is kept as a dep. The materialized astro.config still imports tangly/plugin for the docs runtime, and theme components still import from @tanglydocs/theme-ui.

You manage astro.config.mjs and integrations from then on.

bash
tangly eject --out ./astro-site --yes

add

Scaffold a new page, snippet, or changelog entry.

bash
tangly add <type> <path> [--template <name>] [--no-nav]
Arg / flagTypeDefaultDescription
typepositionalpage | snippet | changelog
pathpositionalSlug or filename. e.g. guides/billing, shared/disclaimer, 1.2.0
--templatestringTemplate name from ./templates/
--no-navbooleanfalseDon’t auto-insert into docs.json navigation

Page

Writes <path>.mdx and inserts the slug into the last navigation.groups (or navigation.pages) entry in docs.json.

bash
tangly add page guides/billing

Snippet

Writes snippets/<path>.mdx. Snippets aren’t inserted into nav (they’re not pages).

bash
tangly add snippet shared/disclaimer

Changelog

Writes changelog/<path>.mdx with an <Update> block ready to fill in. Date is today; version is parsed from the slug if it looks semver-shaped.

bash
tangly add changelog 1.2.0

preview

Serve the built dist/ locally (Astro’s static preview server).

bash
tangly preview [--port 4321] [--out ./dist]
FlagTypeDefaultDescription
--portstring4321Port
--outstring./distOutput directory to serve

Use this to verify the production build before deploying.

bash
tangly build && tangly preview

Source

Last updated Edit this page

Type to search…

↑↓ navigate open esc close