Aliou Diallo

@aliou/sh

Shell parser/AST for POSIX, Bash, mksh, and zsh in TypeScript.

@aliou/sh

TypeScript shell parser inspired by mvdan/sh. Parses POSIX/Bash shell commands into a typed AST.

Zero dependencies. Single exported function. ~28 KB bundled.

Usage

import { parse } from "@aliou/sh";

const { ast } = parse('echo "hello $USER" | grep hello');
// ast.type === "Program"
// ast.body[0].command.type === "Pipeline"

The parser returns a Program node containing Statement nodes. Each statement wraps a Command, which is one of:

Words contain typed parts: Literal, SglQuoted, DblQuoted, ParamExp, CmdSubst, ArithExp, ProcSubst.

Example: extract command names

import { parse, type SimpleCommand } from "@aliou/sh";

function extractCommandNames(node: unknown): string[] {
  if (!node || typeof node !== "object") return [];
  const n = node as Record<string, unknown>;
  const names: string[] = [];

  if (n.type === "SimpleCommand") {
    const cmd = n as unknown as SimpleCommand;
    if (cmd.words?.length) {
      const first = cmd.words[0];
      if (first.parts.length === 1 && first.parts[0].type === "Literal") {
        names.push(first.parts[0].value);
      }
    }
  }

  for (const val of Object.values(n)) {
    if (Array.isArray(val)) {
      for (const item of val) names.push(...extractCommandNames(item));
    } else if (val && typeof val === "object") {
      names.push(...extractCommandNames(val));
    }
  }
  return names;
}

const { ast } = parse("grep -rn npm package.json | head -5");
extractCommandNames(ast); // ["grep", "head"]

Supported syntax

Install

pnpm add github:aliou/sh

Development

Requires Nix (provides Node 22 and pnpm):

nix develop

pnpm install     # install deps
pnpm test        # run tests (vitest)
pnpm typecheck   # tsc --noEmit
pnpm check       # biome format + lint
pnpm build       # rolldown + tsc declarations

Git hooks (via husky):

Status

Work in progress. Covers the Bash subset needed for AST-based command analysis (command classification, variable mutation tracking, guardrail enforcement). Not yet a complete POSIX/Bash parser — notably missing: position tracking in AST nodes, extended globbing, and full arithmetic expression parsing.

License

UNLICENSED