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

@escherize/probe

v0.1.0

Published

Inspect Gleam source files: list top-level declarations with line ranges, types, and signatures.

Readme

gleam-probe

Token-efficient overview of Gleam source files. Built for AI coding agents that need to know what's in a file without reading the whole thing into their context window.

One row per top-level declaration: line range, visibility, kind, signature. A 500-line Gleam file collapses to ~30 lines. The agent reads the index, decides what's relevant, then opens only the lines it needs.

The problem

LLM coding agents waste context reading entire files to figure out "what's in here." A 2000-line module costs thousands of tokens to skim, when the agent only needed to know "is there a parse_url function and what does it return."

gleam-probe ls produces a structural index so the agent can:

  1. List declarations + signatures (cheap).
  2. Decide which one to open.
  3. Read only those lines.

Same idea as clj-surgeon :ls for Clojure or ctags, but emits the kind of structured signal an LLM actually parses well.

Output

Default (optimized for LLM agents — terse, regular, low-token):

src/probe.gleam (16 decls)
imports: argv, gleam/io, gleam/list, glance, glint, simplifile, probe/decl, probe/line_index, probe/render, probe/scan
L12-25 pub fn main() -> Nil
L27-32 fn rewrite_short_help(arg: String) -> String
L34-45 fn root_command() -> glint.Command(Nil)
L47-77 fn ls_command() -> glint.Command(Nil)
L79-101 fn run_ls(patterns: List(String), as_json: Bool, show_doc: Bool) -> Nil

Rules:

  • Imports collapse into one imports: line. Most files have many; rolling them up saves significant tokens.
  • L12 for single-line decls, L12-25 for ranges.
  • pub prefix only when public (absence = private).
  • Signature uses Gleam keyword form: fn, type, opaque type, const.
  • Doc preview appended as -- <first line, truncated> when present.
  • One decl per line. No padding, no marker columns.

With --doc the full doc expands inline, prefixed with /// to match Gleam source convention:

L4-6 pub fn greet(name: String) -> String
    /// Greets a person by name.
    /// Returns the greeting string.

JSON (for tool calls, MCP servers, scripts):

[
  {
    "path": "src/foo.gleam",
    "decls": [
      {
        "kind": "fn",
        "name": "greet",
        "public": true,
        "line_start": 12,
        "line_end": 14,
        "signature": "fn greet(name: String) -> String",
        "params": [{ "label": "", "name": "name", "type": "String" }],
        "return": "String"
      }
    ]
  }
]

Install

npx @escherize/probe ls src/foo.gleam

Or:

npm install -g @escherize/probe
gleam-probe ls src/foo.gleam

Node >= 18. No Gleam toolchain required - ships precompiled JS.

Usage

gleam-probe ls <file-or-glob> [--json] [--doc]
gleam-probe ls -h
gleam-probe -h

<file-or-glob> accepts:

  • single file: src/foo.gleam
  • directory (recursive): src/
  • glob: 'src/**/*.gleam', '*.gleam'

Sorted by line, so output mirrors source order.

JSON (--json) always includes a doc field (empty string when none), regardless of --doc. @attr lines above a decl are skipped during doc extraction.

Recipes for agents

Public API of a module:

gleam-probe ls src/my/api.gleam --json \
  | jq '.[].decls[] | select(.public) | .signature'

Find a function by name across a project:

gleam-probe ls 'src/**/*.gleam' --json \
  | jq -r '.[] | .path as $p | .decls[] | select(.name == "parse") | "\($p):\(.line_start)"'

Token math (rough): the JSON form of a 1500-line, 60-decl Gleam file is ~3-5k tokens. Reading the file itself is ~15-25k. Roughly 4-6x cheaper, and the agent doesn't burn budget on function bodies it didn't need.

Agent integration

Stable JSON shape, exit code 0 on success, errors to stderr. Suitable for:

  • Tool-call wrappers that shell out to the binary
  • MCP servers exposing a "list_declarations" tool
  • Pre-prompt scaffolding ("here is an index of the codebase: ...")
  • Editor integrations that surface symbols without running the LSP

What it parses

Backed by glance, the Gleam parser written in Gleam. Handles: opaque types, type aliases, labeled params, generics, function types, tuple types, attributes.

pub opaque type Box(a) { Box(a) }
pub type Map(k, v) = dict.Dict(k, v)
pub fn map(over list: List(a), with f: fn(a) -> b) -> List(b) { ... }
const default_port: Int = 8080

Glance is permissive - may parse files the official compiler rejects. gleam-probe does no semantic analysis; surfaces what Glance gives it.

Limitations

  • Top-level decls only. No nested lets or expression-level info.
  • No call graph (planned: gleam-probe deps).
  • No source slicing (planned: gleam-probe show <file>:<name>).
  • Comments/docstrings not yet attached to decls (planned).

Development

gleam build --target javascript
gleam test
./bin/gleam-probe.mjs ls src/
gleam run -- ls src/

Layout:

src/
  probe.gleam              # CLI entry (glint)
  probe/
    decl.gleam             # glance AST -> Decl record
    line_index.gleam       # byte offset -> line number
    scan.gleam             # path/glob -> file list
    render.gleam           # table + JSON output
    type_print.gleam       # glance.Type -> string
test/
  probe_test.gleam
bin/
  gleam-probe.mjs          # Node entry shim

Built on

Prior art

  • clj-surgeon - same idea for Clojure
  • ctags / etags - same idea, 1980s
  • LSP documentSymbol - same idea, heavyweight

License

MIT