mrkeyoor.com_
Sat 08 Aug 21:02 UTC
npmCLI & Toolingupdated 08 Aug 2026

@xhmikosr/bin-check

@xhmikosr/bin-check answers one narrow question: can this exact executable path be run successfully with these arguments? It first checks executable permissions with isexe, then launches the process through execa and resolves to true only for exit code zero. It provides asynchronous and synchronous calls and defaults to `--help` when arguments are omitted. It does not search PATH, install binaries, inspect versions, capture output for callers, or let you configure timeouts and environment variables.

Verdict

Useful as a focused smoke test for a known binary path, especially in installers that already target modern ESM Node. Use execa directly when you need any process detail or safety control beyond a boolean exit-code check.

API stability4/5The public contract remains a default function returning Promise<boolean> plus a sync property returning boolean, with an optional argument array and a documented `--help` default. That shape is unusually small and easy to wrap. Runtime and module-format changes are the larger compatibility risk: the current release is ESM-only and requires Node 20, so upgrades across majors can break older CommonJS or Node installations even when call semantics stay familiar.
Docs3/5The README is concise and accurately documents both methods, parameter types, the default argument, and return values with a working example. It does not explain that callers must supply an exact path rather than a PATH command, distinguish thrown executability errors from false process exits, mention the lack of timeout control, provide TypeScript guidance, or show cross-platform probing. Reading the 35-line source answers those questions, but the guide should.
Maintenance5/5Version 8.2.2 was published in June 2026 and GitHub reports a repository push on August 2, 2026. The repository is not archived, its workflow badge points to active CI, and the current open_issues_count is zero, meaning no open issues or pull requests in GitHub's combined count. Dependencies are on current major lines for execa and isexe, though the project is small enough that maintenance is concentrated.
Ecosystem3/5The package records 4,010,264 weekly downloads and composes two established process utilities, which gives it broad transitive reach in binary installer chains. Direct ecosystem value is limited: it has no plugins, no declared TypeScript types, no CommonJS build, and no configuration surface. Most teams needing richer behavior will use execa, while PATH discovery is better served by which or command-exists.

Use it if

  • You ship or download a helper executable and need a quick post-install smoke test against its exact path
  • You want to distinguish a missing or non-executable file from a command that ran and returned a failing exit code
  • You need the same tiny boolean check in asynchronous setup code and synchronous startup code
  • Your project is ESM-only on Node 20 or newer and already accepts execa in its dependency tree
Skip it if

Setup reality

Install with `npm install @xhmikosr/bin-check`. Version 8.2.2 requires Node 20 or newer, is marked `type: module`, and exposes only an ESM default export, so `require()` is not a supported entry path. There are no peers, native builds, credentials, or config files, but the runtime dependency chain includes execa 9.6.1 and isexe 4.0.0. Pass an actual executable path, not merely a command such as `git`: bin-check runs isexe against the supplied string and does not perform shell or PATH resolution. If the file is missing or lacks executable permission, the promise rejects or the sync call throws with a permissions-oriented error. If the file launches and exits nonzero, the result is false because execa is called with `reject: false`. Those are different failure channels and production setup code should handle both. Omitting the arguments array uses `['--help']`; that is not universally safe because some tools lack `--help`, write it to stderr, open a UI, wait for input, or return nonzero for help. Pick a fast, side-effect-free probe such as `--version` when the target documents one. There is no timeout or AbortSignal option, so a hanging binary can hang the check. The synchronous method blocks Node's event loop and belongs in short startup or install scripts, not request handling. TypeScript users need a local declaration or an untyped import because the package publishes no declaration file.

Patterns

Check an executable asynchronouslycheck-binary-async

import binCheck from '@xhmikosr/bin-check'

const works = await binCheck('/usr/bin/tool', ['--version'])
if (!works) throw new Error('tool returned a failing exit code')

Use an exact path. A bare command name is not resolved through PATH before the executability check.

Use the default help probeuse-default-probe

import binCheck from '@xhmikosr/bin-check'

const works = await binCheck('/usr/bin/tool')

Omitting arguments runs `--help`; confirm that the target supports it and exits zero without waiting for input.

Distinguish launch errors from bad exit codeshandle-check-errors

try {
  const works = await binCheck(binaryPath, ['--version'])
  if (!works) console.error('Executable ran but exited nonzero')
} catch (error) {
  console.error('Missing or not executable:', error.message)
}

A non-executable path rejects; a successfully launched process with a nonzero exit code resolves false.

Run a synchronous startup checkcheck-binary-sync

import binCheck from '@xhmikosr/bin-check'

if (!binCheck.sync('/usr/bin/tool', ['--version'])) {
  throw new Error('tool failed its startup probe')
}

The sync form blocks the event loop until the child exits and has no timeout, so keep it out of request handlers.

Smoke-test the current Node executablecheck-node-runtime

import process from 'node:process'
import binCheck from '@xhmikosr/bin-check'

const works = await binCheck(process.execPath, ['--version'])

process.execPath is an absolute path, which matches bin-check's exact-path requirement.

Select a packaged binary by platformcheck-platform-binary

import path from 'node:path'
import process from 'node:process'
import binCheck from '@xhmikosr/bin-check'

const filename = process.platform === 'win32' ? 'tool.exe' : 'tool'
const binaryPath = path.join(packageRoot, 'bin', process.platform, process.arch, filename)
const works = await binCheck(binaryPath, ['--version'])

A real binary package must also map unsupported platform and architecture combinations before calling bin-check.

Set Unix permissions before probing a downloadset-executable-permission

import { chmod } from 'node:fs/promises'
import binCheck from '@xhmikosr/bin-check'

if (process.platform !== 'win32') await chmod(binaryPath, 0o755)
const works = await binCheck(binaryPath, ['--version'])

Only change permissions on a file you installed and verified; bin-check does not repair permissions itself.

Probe several known executable pathscheck-several-binaries

const probes = [
  ['/opt/tools/a', ['--version']],
  ['/opt/tools/b', ['version']],
]

const results = await Promise.all(probes.map(async ([file, args]) => ({
  file,
  works: await binCheck(file, args),
})))

Any missing or non-executable path rejects Promise.all; use Promise.allSettled when every diagnostic must be retained.

Alternatives

PackageRegistryPick it when
execanpmChoose it when you need output, timeout, cancellation, environment, cwd, or detailed process errors
command-existsnpmChoose it when the real question is whether a command name can be resolved on PATH
whichnpmChoose it to resolve command names to executable paths before deciding how to probe them
isexenpmChoose it when checking file executability is enough and launching the program would be undesirable