npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@textscene/linter

v2.0.0

Published

Command-line linter for Godot .tscn scenes and .tres resources, with every check grounded in the Godot source.

Readme

@textscene/linter

tscn-lint checks Godot .tscn scenes and .tres resources, without a Godot install. It reports syntax errors with line and column, then missing resources, invalid references and property values that Godot refuses or changes. Every check is grounded in Godot's own source (ADR-0032).

Install

Requires Node.js 24 or later.

npm install --global @textscene/linter

Or run it once: npx @textscene/linter scenes/

Usage

tscn-lint scenes/main.tscn            # one file
tscn-lint scenes/*.tscn levels/*.tscn # several files
tscn-lint scenes/                     # every .tscn and .tres file underneath
tscn-lint --no-color scenes/          # no ANSI colours

Project files

When the scene's own directory, or a directory above it, holds project.godot, tscn-lint resolves res:// paths from there. For a scene outside every Godot project but inside the directory tscn-lint runs from, it resolves them from the scene's own directory. tscn-lint then also reads each .glb and .gltf file the scene uses, and reports one that requires a glTF extension Godot's importer does not support. Where a sub-resource, a .tres [resource] body, a connection or the scene's root node uses the glTF file, Godot fails to load the scene or resource that uses it. The report is then an error when project.godot enables no editor plugin and declares no autoload, and no directory Godot's editor scans holds a .gdextension file. Otherwise, and always for a scene outside every Godot project, it is a warning, because an editor plugin, an autoload or a GDExtension can add support for the extension. Where only other nodes use the glTF file, the scene loads without it, and the report is always a warning. tscn-lint reads the .gdextension files themselves, so a fresh checkout without .godot/ gets the same answer as the editor. tscn-lint checks a scene alone when it lies outside every Godot project and outside the directory tscn-lint runs from, so a run never reads a large directory such as /tmp.

Output formats (--format)

  • text (default): coloured, streamed per file.

  • json: one JSON array with one finding per diagnostic:

    {
      "file": "scenes/broken.tscn",
      "line": 4,
      "column": 12,
      "severity": "error",
      "rule": "format:transform",
      "message": "Property 'transform' must be Transform3D with 12 numbers like Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0), got: \"Transform3D(invalid, values, here)\"",
      "nodeType": "Node3D",
      "nodeName": "Root"
    }

    rule names the check. A refused property value names its property as format:<property>, such as format:transform. A syntax error is strict-parser. line and column are null for a finding about the whole file, such as file-read-error.

  • github: GitHub Actions annotations on the diff. It is the default when $GITHUB_ACTIONS=true.

Every format writes a control character from a scene, such as ESC, as a visible escape (\u001b), so a scene cannot send a command to your terminal.

Exit codes

| Code | Meaning | | --- | --- | | 0 | No errors. Warnings and info do not fail the run. | | 1 | An error, or a file that could not be read. | | 2 | An unknown --format value. |

Build from source

From the repository root:

pnpm install
pnpm --filter @textscene/linter build

The bundle has no React or three.js. ARCHITECTURE.md in the repository describes how the linter imports each node slice.