Skip to content

Scripted Tools — Project Layout & Generated Files

A trailmap project is source you author plus scaffolding the framework generates. Short version: commit your .yaml manifests, your .ts tools, and the one generated .gitignore. Everything else is regenerated automatically and already ignored for you.

Writing the tools themselves? Start with Scripted Tools (TypeScript) — the type-safe authoring surface (trailblaze.tool<I, O>(...), typed inputs, composing tools). This page just covers the files that authoring leaves in your project.

my-project/
├── package.json                        generated · COMMIT   install bootstrap
└── trails/
    ├── .trailblaze/                     generated · ignore   vendored SDK + tsc cache
    └── config/
        ├── trailblaze.yaml              SOURCE   · commit    workspace config
        ├── dist/                        generated · ignore   compiled manifests
        └── trailmaps/myapp/
            ├── trailmap.yaml            SOURCE   · commit    the manifest
            ├── .gitignore               generated · COMMIT   ignores the two files below
            └── tools/
                ├── myapp_login.ts           SOURCE   · commit    your tool
                ├── myapp_login.test.ts      SOURCE   · commit    your test
                ├── tsconfig.json            generated · ignore   editor type-check config
                └── trailblaze-client.d.ts   generated · ignore   this trailmap's typed tool API

You only ever write the .yaml manifests and your type-safe .ts tools. Everything marked generated is written by trailblaze check — you never edit or maintain it.

What to commit

  • Your source — the .yaml manifests and your .ts tools and tests.
  • The per-trailmap .gitignore — the framework writes it; committing it is what hides the generated files for everyone who clones (it also travels with a vendored/published trailmap).
  • package.json (first run only) — a tiny bootstrap that regenerates typings on a fresh npm/bun install.

That’s it. Everything else — trailblaze-client.d.ts, tsconfig.json, .trailblaze/, dist/ — is generated, including trailblaze-client.d.ts, this trailmap’s typed tool API (the bindings that make ctx.tools.<name>(args) autocomplete against the exact set of tools your trailmap can dispatch). You don’t commit any of it, and you don’t set up the ignoring either — check writes the .gitignore and seeds your local .git/info/exclude, so generated files never clutter git status.

Don’t commit tools/tsconfig.json

It’s tempting to commit it — it’s the file your editor reads, so a fresh clone with no tsconfig.json shows red squiggles until someone runs check. Commit it anyway and you inherit two problems, because the file is workspace-relative and machine-generated:

"paths": {
  "@trailblaze/scripting": ["../../../../.trailblaze/sdk/dist/index"]
}
  1. It doesn’t buy you a working fresh checkout. That path points into trails/.trailblaze/, which is itself generated and ignored. A committed tsconfig.json on a fresh clone resolves @trailblaze/scripting to a directory that isn’t there yet, so bun test and your editor still need trailblaze check first — exactly what committing it was supposed to avoid.
  2. The .. climb is counted from where the trailmap sits. It’s correct only while every consumer keeps the trailmap at the same depth below the workspace root. Vendor or copy the trailmap into a project that nests it differently and the committed paths point outside that workspace, so every tool in it fails with Cannot find module '@trailblaze/scripting'.

Run trailblaze check instead. It’s one command, it writes the paths for the workspace it’s running in, and the .gitignore it maintains keeps the result out of git status.

Committing a generated file anyway

If you do need one committed, say so by negating the entry in the trailmap’s .gitignore:

!tools/tsconfig.json

check treats a negated entry as already handled and won’t re-add the plain one, so the file stops reappearing in git status on every run. Negate it rather than just deleting the line: git ignore rules never apply to a file that’s already tracked, so deleting the line looks fine in the repo you committed from, but a fresh copy of the trailmap tracks nothing yet — and there the entry silently keeps your committed file out of git add. The negation travels with the trailmap, and it also overrides the .git/info/exclude rule check seeds locally.

Remove the negation when you stop committing the file. The negation is what tells check the path is deliberately yours, so it keeps suppressing the plain entry after the committed file is gone — and then nothing ignores the regenerated one. The symptom is a tools/tsconfig.json that shows up as untracked in git status after every check, in every clone.

Why aren’t the typed bindings committed?

They’re coupled to your installed Trailblaze version: the tool surface — and so the generated bindings — can change with every release, so a committed copy would just go stale. That tight coupling is also why they’re generated to disk rather than shipped as a versioned npm package — the Trailblaze you have installed is the source of truth, and it writes types that match it.

So you need Trailblaze installed to get autocomplete — the types come from it — and you already do. It generates them for you, usually without you asking: the daemon runs codegen on your first device command, trailblaze check does it on demand, and npm/bun install triggers it through the bootstrap package.json.

More