Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@master4n/master-cli

Package Overview
Dependencies
Maintainers
1
Versions
54
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@master4n/master-cli - npm Package Compare versions

Comparing version
3.0.2
to
3.0.3
+3
bin/catalog.agent.d.ts
import type { CommandInfo } from './catalog';
/** Agent generation 1: token savers and deterministic ground-truth commands. */
export declare const AGENT_COMMANDS: readonly CommandInfo[];
import type { CommandInfo } from './catalog';
/** The original toolkit: discovery, time, crypto primitives, OS/filesystem. */
export declare const CLASSIC_COMMANDS: readonly CommandInfo[];
import type { CommandInfo } from './catalog';
/**
* Agent generation 3: OS-level commands — the things an agent normally needs
* platform-specific incantations (or a human's hands) for, made one-call and
* safe-by-default on macOS, Windows, and Linux.
*/
export declare const OS_COMMANDS: readonly CommandInfo[];
import type { CommandInfo } from './catalog';
/**
* Agent generation 2: the commands an AI coding agent reaches for constantly —
* code navigation, dependency tracing, bulk edits, readiness waits, and
* environment drift checks.
*/
export declare const POWER_COMMANDS: readonly CommandInfo[];
declare const base: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => undefined;
};
export default base;
declare const calc: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => undefined;
};
export default calc;
declare const caseCmd: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<void>;
};
export default caseCmd;
declare const clip: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<void>;
};
export default clip;
declare const count: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default count;
declare const cron: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => undefined;
};
export default cron;
/**
* Minimal, dependency-free 5-field cron engine (minute hour day-of-month month
* day-of-week). Supports * , - / lists, ranges, and steps. Standard semantics:
* when BOTH dom and dow are restricted, a date matches if EITHER matches (Vixie
* cron rule).
*/
export interface CronFields {
minute: Set<number>;
hour: Set<number>;
dayOfMonth: Set<number>;
month: Set<number>;
dayOfWeek: Set<number>;
domRestricted: boolean;
dowRestricted: boolean;
}
export declare function parseCron(expression: string): CronFields;
/** Next `count` run times strictly after `from` (local time), bounded to 5 years. */
export declare function nextRuns(f: CronFields, from: Date, count: number): Date[];
declare const diff: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default diff;
declare const disk: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default disk;
declare const dns: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<void>;
};
export default dns;
declare const dotenv: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => undefined;
};
export default dotenv;
declare const env: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => void;
};
export default env;
/**
* TTY-only fallback for `mfn epoch` when no flags/positional are supplied.
* Lives in its own module to keep epoch.ts focused on the headless paths
* (and under the 150-line file budget).
*/
export declare function epochInteractive(argv: any, epochToDate: (argv: any, value: number) => void, dateToEpoch: (argv: any, input: string, format?: string, tz?: string) => void): Promise<void>;
declare const escapeCmd: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default escapeCmd;
declare const ext: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => undefined;
};
export default ext;
declare const freq: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default freq;
declare const have: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default have;
declare const http: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default http;
declare const imports: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<void>;
};
export default imports;
declare const ip: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => void;
};
export default ip;
declare const jsonCmd: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<void>;
};
export default jsonCmd;
declare const lines: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default lines;
declare const notify: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default notify;
declare const openCmd: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default openCmd;
declare const outlineCmd: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default outlineCmd;
/**
* Regex-based source outliner. Not a real parser — it's the 95% answer in
* ~zero time: top-level symbols with line numbers, so an agent can read a
* 50-token outline and then fetch only the lines it needs (`mfn lines`).
*/
export interface Symbol {
line: number;
kind: string;
name: string;
exported: boolean;
}
export declare const SUPPORTED_EXTENSIONS: string[];
export declare function outline(text: string, extension: string): Symbol[];
declare const pkgCmd: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => undefined;
};
export default pkgCmd;
declare const ports: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default ports;
declare const procs: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default procs;
declare const recent: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => undefined;
};
export default recent;
declare const regex: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default regex;
declare const replace: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => undefined;
};
export default replace;
declare const repo: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default repo;
declare const schema: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default schema;
declare const semver: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => void;
};
export default semver;
declare const size: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => undefined;
};
export default size;
declare const sys: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => void;
};
export default sys;
declare const trash: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<undefined>;
};
export default trash;
declare const url: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => undefined;
};
export default url;
declare const wait: {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => Promise<void>;
};
export default wait;
/**
* Shape every command module exports and `src/index.ts` registers. Typing the
* registration (instead of `any`) means a malformed command module fails the
* typecheck instead of failing at runtime.
*/
export interface CliCommand {
/** yargs command spec, e.g. `epoch <value>` or `sc [pattern]`. */
command: string;
/** One-line description shown in `mfn -h`. */
describe: string;
/** yargs builder adding the command's options/examples. */
builder: (yargs: any) => any;
/** Command implementation; receives parsed argv. */
handler: (argv: any) => void | Promise<void>;
}
/**
* True when reading this file's CONTENT would expose credentials/keys/PII.
* Checks the literal path AND the resolved realpath, so an innocently named
* symlink ("notes.txt" → "~/.ssh/id_rsa") can't smuggle a secret past the
* basename check (found by an adversarial review).
*/
export declare function isSensitivePath(p: string): boolean;
/** Standard refusal message for a sensitive path (stable error: SensitivePath). */
export declare const sensitivePathMessage: (p: string) => string;
/** Returns what kind of secret the text contains, or null when none detected. */
export declare function scanSecrets(text: string): string | null;
/**
* Mask secret-shaped substrings inside text that a command echoes back. This
* is the content-level backstop to isSensitivePath's path-level check: even
* when a secret arrives via stdin (`cat .env | mfn freq`) — where there is no
* path to vet — a JWT/private key/cloud token is replaced before it reaches
* stdout. Returns the (possibly) masked text and how many tokens were masked.
*/
export declare function redactSecrets(text: string): {
text: string;
redactedCount: number;
};
/**
* True for URLs that must never be probed: cloud metadata services. Local
* dev servers (localhost/127.0.0.1) stay allowed — probing them is the point.
*/
export declare function isBlockedUrl(url: URL): boolean;
export declare const blockedUrlMessage: (url: string) => string;
/**
* Rewrite yargs' "Unknown argument: X" into an agent-actionable message when X
* is the attempted command: name the problem correctly, suggest the nearest
* real command, and point at `mfn capabilities`.
*/
export declare function improveUnknownCommandMessage(msg: string): string;
# Security Policy
## Reporting a vulnerability
Please open a private report via
[GitHub Security Advisories](https://github.com/Master4Novice/master-cli/security/advisories/new)
rather than a public issue. You should receive a response within a week.
## Threat model & design guarantees
`mfn` is a local developer tool. It is designed so that untrusted *input*
(strings, tokens, file contents, port numbers) can never escalate into code
execution or unintended process termination:
- **No shell interpolation.** Every external process (`npm`, `lsof`, `netstat`,
`kill`, `taskkill`) is spawned with `execFile` — arguments are passed as an
array, never interpolated into a shell string. A crafted package name or port
value cannot inject commands.
- **Strict input validation.** Ports must be integers in 1..65535; counts,
sizes, and byte lengths have hard upper bounds; PIDs parsed from `lsof`/
`netstat` output must be strictly numeric before being passed to `kill`.
- **JWTs are decoded, never verified or transmitted.** `mfn decode` performs
local base64url decoding only; the token never leaves the machine, and the
output explicitly states the signature is not verified.
- **Crypto uses Node's CSPRNG.** `random` and `id` use `node:crypto`
(`randomBytes`, `randomUUID`) with rejection sampling — no `Math.random`, no
modulo bias.
- **Local cache is private.** `~/.mfn/cache` (recent ports, ignore lists) is
created with mode `0700`.
- **No network calls** except `mfn update`, which delegates to `npm` itself.
- **No telemetry.** Nothing is collected or sent anywhere.
## Guardrails (active, no override flags)
`mfn` is built to be safe to hand to an AI agent. These guardrails are always
on — there are deliberately **no bypass flags**, because an agent will find and
use any flag that exists:
| Guardrail | Commands | What it prevents |
| --------- | -------- | ---------------- |
| **Sensitive-path refusal** (`SensitivePath`, exit 2) | `lines` `json` `schema` `diff` `freq` `regex -f` | Returning the CONTENT of credential stores: `~/.ssh`, `~/.aws`, `~/.gnupg`, `~/.kube`, `.env*`, `*.pem`, `*.key`, `id_rsa*`, `.npmrc`, `.netrc`, `shadow`, … An agent's context window is a log that never rotates. |
| **Clipboard secret redaction** | `clip` (read) | Passwords/tokens pasted through the clipboard (password managers). Secret-shaped content (private-key blocks, JWTs, AWS/GitHub/Slack/Google/npm/`sk-` tokens) is withheld with `redacted:true`. |
| **Env value scanning** | `env` | Redacts by NAME pattern (key/token/secret/…) **and** by VALUE shape — an innocently named variable holding a JWT is still redacted. `mfn env` with no names lists names only. |
| **Dotenv never reads values** | `dotenv` | Compares KEY presence between `.env` and `.env.example`; values are never parsed, stored, or returned. |
| **Cloud-metadata block** (`BlockedTarget`, exit 2) | `http` `wait -u` | SSRF credential theft via `169.254.169.254`, `metadata.google.internal`, Alibaba/AWS v6 endpoints. Localhost stays allowed — probing your own dev server is the point. |
| **Session-cookie redaction** | `http` | `set-cookie` response headers are replaced with `[redacted: session cookie]`. |
| **Scheme allow-list** | `open` | Only http(s) URLs or existing local paths; `javascript:`, `file:`, and custom protocol handlers are refused. |
| **Reversible delete only** | `trash` | Moves to the OS trash (never unlink); refuses `/`, home, cwd, and any parent of cwd — compared by realpath so symlinks can't fool it. |
| **PID floor + numeric check** | `kill` | A parsing surprise can never become `kill -9 0/1/-1`; ports validated 1..65535. |
| **Tool-name charset** | `have` | Probed names must be plain command names — no paths, no metacharacters. |
| **Dry-run by default** | `replace` | File modification requires explicit `--write`; scope is bounded to cwd. |
| **Body/range caps everywhere** | `http` (2KB preview) `lines` (2000) `diff` (20k lines) `clip` (1MB) … | One call can never flood a context window or memory. |
## Guardrail scope & known limits (honest)
The credential guardrail is **defense-in-depth, not a security boundary**. It is
two layers:
1. **Path layer** — refuses sensitive paths, resolving symlinks via realpath so
an innocently named symlink can't smuggle a secret file's content out.
2. **Content layer** — masks secret-*shaped* substrings (private-key blocks,
JWTs, AWS/GitHub/Slack/Google/npm/`sk-` tokens) in the content that
`lines`/`freq`/`regex`/`json` echo, **including content piped via stdin**
where there is no path to vet.
Known limits, stated plainly:
- **Hardlinks** to a sensitive file are not detected at the path layer (a
hardlink shares the file's inode but has no distinguishable path). The content
layer still masks recognised token shapes; and creating a hardlink requires
the same read access as reading the original, so it grants no new capability.
- The content layer matches **known token shapes**, not arbitrary `KEY=value`
secrets — over-broad redaction would break legitimate config/log processing.
- An agent that already has shell access can read any file directly with `cat`.
These guardrails reduce *accidental* exposure through `mfn`'s own output
(the common path by which secrets leak into an agent's context window); they
are not a sandbox and do not claim to be.
## Scope notes
- `mfn hash` supports `md5`/`sha1` for checksum interop with legacy systems —
they are not suitable for security purposes; use `sha256`/`sha512`.
- `mfn kill` sends `SIGKILL` to processes the invoking user owns; it cannot
affect other users' processes beyond what the OS already permits.
- `mfn update <package>` installs a named package globally via npm — only point
it at packages you trust, exactly as with `npm install -g`.
## Supported versions
Only the latest published major (3.x) receives security fixes.
+5
-1
/**
* Single source of truth for the command catalogue — consumed by the welcome
* banner (the "tools" line) and by `mfn capabilities` (the agent-facing
* manifest). Keep this in sync when adding a command.
* manifest). Add new commands to the matching catalog.*.ts data module.
*/

@@ -9,2 +9,4 @@ export interface CommandInfo {

name: string;
/** Functional grouping an agent can filter on. */
category: 'discovery' | 'time' | 'crypto' | 'text' | 'data' | 'code' | 'net' | 'system';
/** One-line human summary. */

@@ -16,1 +18,3 @@ summary: string;

export declare const COMMANDS: readonly CommandInfo[];
/** Distinct categories in catalogue order (for grouped rendering). */
export declare const CATEGORIES: readonly string[];

@@ -14,2 +14,39 @@ import cts from './cts';

import port from './port';
export { cts, sc, deco, date, epoch, killProcess, update, capabilities, id, hash, encode, random, port, };
import jsonCmd from './json';
import count from './count';
import lines from './lines';
import have from './have';
import sys from './sys';
import repo from './repo';
import calc from './calc';
import semver from './semver';
import caseCmd from './case';
import cron from './cron';
import diff from './diff';
import env from './env';
import size from './size';
import ext from './ext';
import freq from './freq';
import regex from './regex';
import url from './url';
import ip from './ip';
import escapeCmd from './escape';
import schema from './schema';
import outlineCmd from './outline';
import imports from './imports';
import replace from './replace';
import recent from './recent';
import pkgCmd from './pkg';
import dotenv from './dotenv';
import wait from './wait';
import ports from './ports';
import http from './http';
import base from './base';
import clip from './clip';
import notify from './notify';
import openCmd from './open';
import procs from './procs';
import disk from './disk';
import trash from './trash';
import dns from './dns';
export { cts, sc, deco, date, epoch, killProcess, update, capabilities, id, hash, encode, random, port, jsonCmd, count, lines, have, sys, repo, calc, semver, caseCmd, cron, diff, env, size, ext, freq, regex, url, ip, escapeCmd, schema, outlineCmd, imports, replace, recent, pkgCmd, dotenv, wait, ports, http, base, clip, notify, openCmd, procs, disk, trash, dns, };
export * from './InquirerPrompt';
export * from './ProcessInfo';
export * from './CliCommand';
+1
-1

@@ -8,3 +8,3 @@ export declare function Logger(): {

export declare function CommandBuilder(instance: any): {
add: (alias: string, describe: string, builder: object, handler: (argv: any) => any) => void;
add: (alias: string, describe: string, builder: (yargs: any) => any, handler: (argv: any) => void | Promise<void>) => void;
};

@@ -11,0 +11,0 @@ /**

+112
-43
# @master4n/master-cli (`mfn`)
> A headless-friendly developer CLI that replaces boilerplate agents otherwise
> regenerate on every machine: epoch/date conversions, JWT decoding, freeing
> ports, finding files, and printing directory trees. Every command is designed
> to be called by both humans and AI agents.
> 50 headless, JSON-first commands for AI agents and developers: extract instead
> of dump (token savers), compute instead of guess (hallucination killers),
> one-call system/code/network facts, and cross-platform OS actions (clipboard,
> notifications, trash, processes). Every command behaves identically for a
> human at a terminal and an agent reading stdout.
## Agent contract (read this first)
- **Zero-install:** `npx -y @master4n/master-cli <command> --json` works without a
global install; with it installed, the binary is `mfn`.
- **Discover commands:** `mfn capabilities --json` returns the full manifest
(`{ name, version, bin, conventions, commands:[{name,summary,examples}] }`).
(`{ name, version, bin, conventions, docs, categories, commands:[{name,category,summary,examples}] }`).
- **Machine output:** pass `--json`, OR just pipe the command (when stdout is not

@@ -16,44 +19,110 @@ a TTY the CLI auto-emits JSON). Output is exactly one object on stdout:

- **Exit codes:** `0` success · `1` runtime error · `2` usage error.
- **Clean channels:** the welcome banner, spinners, and logs go to **stderr**;
**stdout carries only the JSON result**, so `mfn <cmd> --json | jq` always works.
- **No prompts in headless mode:** interactive prompts appear only on a TTY when
required input is missing; with `--json` or when piped, commands never block.
- **Strict parsing:** unknown commands, unknown flags, and missing required
arguments are rejected with `{ "ok": false, "error": "UsageError", ... }` and
exit `2` — a typo never silently "succeeds".
- **Clean channels:** banners/spinners/logs go to **stderr**; **stdout carries only
the JSON result**, so `mfn <cmd> --json | jq` always works.
- **No prompts in headless mode:** with `--json` or when piped, commands never block.
- **Strict parsing:** unknown commands/flags and missing args → `{ok:false, error:"UsageError"}`, exit 2.
- **Fast:** ~60ms per invocation; heavy/TTY-only deps load lazily.
## Commands
## Token savers (read less, extract exactly)
- `mfn id [-t uuid|uuid7|nano] [-n count] [--size N] --json` — generate ids. UUID v4
(default), time-ordered UUID v7 (RFC 9562), or a URL-safe nano id. Returns `{ type, count, ids }`.
- `mfn hash [text] [-a md5|sha1|sha256|sha512] [-f file] [-e hex|base64|base64url] --json`
— hash a string, a file, or piped stdin. Returns `{ algo, encoding, source, bytes, hash }`.
- `mfn encode [text] [--as base64|base64url|hex|url] [-d] --json` — encode (or `-d` decode)
text or stdin. Returns `{ operation, codec, input, output }`.
- `mfn random [-b bytes] [-e hex|base64|base64url] | [-p [-l length]] --json` — secure random
bytes, or an unbiased password. Returns `{ kind, ..., value }`.
- `mfn port [--json] | [-c port] | [-n count]` — find free port(s), or check a specific port.
Returns `{ port }` / `{ count, ports }` / `{ port, available }`.
- `mfn epoch <value> [--tz] [--format] --json` — epoch → date (unit auto-detected:
s/ms/µs/ns). `mfn epoch --from <dateString> [--format] [--tz] --json` — date → epoch.
Fractional/invalid epochs fail with exit 1.
- `mfn date [from] [--tz] [--format] [--in-format] [--in-tz] --json` — convert/format
a date across timezones; omit `from` for now. Returns epoch + UTC + target-zone.
- `mfn decode -t <jwt> --json` — decode a JWT's header and payload (signature NOT verified).
If the payload has a numeric `exp`, also returns `expiry: { exp, expired, expiresInSeconds }`.
- `mfn kill -p <port...> [-y] --json` — kill the process(es) listening on the given
ports. Headless/`--json` (and `-y`) kill all matches without prompting; in headless
mode you MUST pass `-p` (no cached-port replay). Returns `{ killed, failed, notFound }`.
- `mfn sc [pattern] [--ignore...] [--depth] [--limit] --json` — fuzzy-find files/folders
under the current directory. Returns `{ pattern, root, count, truncated, matches }`.
- `mfn cts [--type text|svg|png|jpeg] [--ignore...] --json` — print the directory tree as
text (default) or export it to an image. Ignores node_modules/.git/.nx by default.
- `mfn update [package] --json` — update the CLI (or a named package) globally via npm.
- `mfn capabilities --json` — self-describing manifest of all of the above.
- `mfn json [query] [-f file] [--keys] [--length] --json` — one value from JSON by
dot/bracket path (`scripts.build`, `users[0].name`); stdin or file. Don't read the document.
- `mfn schema [query] [-f file] --json` — infer JSON shape (dot-paths → types, arrays
sampled). A 10MB payload becomes ~20 lines.
- `mfn count [text] [-f file] --json` — lines/words/chars/bytes + `tokensEstimate`
(~4 chars/token heuristic). Know the cost before reading.
- `mfn lines <file> [-s start] [-e end | -n count] --json` — exact 1-based line range,
capped at 2000 lines. Returns `totalLines` too.
- `mfn outline <file> [-k kind] [-e] --json` — symbols + line numbers for
.ts/.tsx/.js/.jsx/.py/.go/.md. Pair with `lines` to read only what matters.
- `mfn diff <a> <b> [-s] --json` — structured hunks `{aStart,aLines,bStart,bLines,removed,added}`;
`-s` for locations/counts only.
- `mfn freq [file] [-t top] [-m min] --json` — most repeated lines (log triage in one call).
- `mfn imports [file] | --who <module> --json` — a file's imports (grouped
relative/packages/builtin), or every file importing a module.
- `mfn repo [-n commits] --json` — git branch, staged/unstaged/untracked counts,
ahead/behind, remotes, recent commits. Replaces 4-5 git calls.
- `mfn sys --json` — OS, arch, node, CPU, memory, user, shell, timezone, cwd in one object.
- `mfn have <tools...> --json` — which tools exist, their path + version, in one call.
- `mfn size [dir] [-t top] --json` / `mfn ext [dir] --json` / `mfn recent [dir] [-t top] --json`
— disk usage, project composition by extension, newest files.
- `mfn ports [--min N] --json` — ALL listening TCP ports with pid/command.
- `mfn ip [-a] --json` — local interfaces/addresses; `primaryIPv4` convenience field.
- `mfn pkg [name] --json` — declared vs installed dependency versions; `missing` list.
- `mfn env [names...] [-p prefix] --json` — env vars; secret-looking values are
ALWAYS redacted; no names → name list only.
- `mfn dotenv [-f .env] [-e .env.example] --json` — missing/extra keys; values never read.
## Exact computation (never guess)
- `mfn calc <expr> --json` — `+ - * / % ^` with parens; integer math in BigInt
(`2^53 + 1` → `9007199254740993`, exact). `exact:true|false` flag in output.
- `mfn base <value> [-f hex|dec|bin|oct] --json` — 0xff/0b1010/0o755/decimal → all bases, BigInt-safe.
- `mfn semver <versions...> [-b major|minor|patch] [-s] --json` — validate/compare/sort/bump
per semver.org (prerelease ordering correct).
- `mfn cron <expr> [-n next] --json` — validate 5-field cron (+ @daily etc.), plain-English
description, next run times (local + ISO + epochMs).
- `mfn regex <pattern> [text] [-f file] [--flags imsuvy] --json` — all matches with
line/index/groups. Test, don't assume.
- `mfn url <value> --json` — components + decoded query params (repeats → arrays).
- `mfn escape [text] [-a shell|json|regex|html|url|string] --json` — context-exact escaping.
- `mfn case [text] [-t camel|snake|kebab|pascal|constant|dot|path|title|sentence|lower|upper] --json`
— identifier style conversion; omit `-t` for all styles.
- `mfn epoch <value> --json` / `mfn epoch --from <date> --json` — epoch ↔ date
(unit auto-detected s/ms/µs/ns).
- `mfn date [from] [--tz] [--format] --json` — date across timezones (IANA), defaults to now.
- `mfn decode -t <jwt> --json` — JWT header+payload+expiry (signature NOT verified).
## Actions (do, don't script)
- `mfn replace <search> <replacement> -g <glob> [--write] --json` — literal find/replace
across files; DRY-RUN by default, `--write` to apply; per-file counts.
- `mfn wait [-p port | -u url | -f file] [-t seconds] --json` — block until ready;
replaces sleep-and-retry loops. Exit 1 on timeout.
- `mfn kill -p <ports...> [-y] --json` — kill listeners on ports (headless: needs explicit -p).
- `mfn http <url> [-m GET|HEAD] [-H "Name: value"] --json` — status/headers/timing
+ body preview capped at 2KB (never a full dump). Exit 1 on non-2xx.
- `mfn port [-c port | -n count] --json` — find free port(s) / check one.
- `mfn id [-t uuid|uuid7|nano] [-n count] --json` — UUID v4, time-ordered v7 (RFC 9562), nano.
- `mfn hash [text] [-a md5|sha1|sha256|sha512] [-f file] --json` — digest of string/file/stdin.
- `mfn encode [text] [--as base64|base64url|hex|url] [-d] --json` — encode/decode (strict charset).
- `mfn random [-b bytes] | [-p [-l length]] --json` — CSPRNG bytes / unbiased password.
- `mfn sc [pattern] [--depth] [--limit] --json` — fuzzy file find under cwd.
- `mfn cts [--type text|svg|png|jpeg] --json` — directory tree.
- `mfn update [package] --json` — global npm update of the CLI (or named package).
## OS-level (cross-platform: macOS / Windows / Linux)
- `mfn clip [text] [-r] --json` — read/write the system clipboard. Write via arg or
stdin (`git diff | mfn clip`); read returns `{chars, text}`. Headless sessions fail
cleanly with `ClipboardUnavailable`.
- `mfn notify <message> [-t title] --json` — desktop notification (osascript /
notify-send / WinRT toast). Ping the user when a long task finishes.
- `mfn open <target> --json` — open an http(s) URL or existing file in the default
app/browser. Non-http schemes and missing paths are rejected (exit 2).
- `mfn procs [pattern] [-t top] --json` — search processes by name: pid/cpu/memMB,
sorted by cpu. One call instead of ps|grep (or tasklist parsing).
- `mfn disk [-a] --json` — per-mount totals/free/used% (df -kP / Win32_LogicalDisk).
- `mfn trash <paths...> --json` — move to the OS trash (reversible; ~/.Trash, XDG
spec, Recycle Bin). Refuses root/home/cwd and parents of cwd. Use instead of rm.
- `mfn dns <hostname> [-t a|aaaa|cname|mx|txt|ns] --json` — system resolver +
record sweep; missing record types are null, not errors.
## Guardrails (always on — there are no bypass flags)
- File-content commands (`lines` `json` `schema` `diff` `freq` `regex -f`) refuse
credential/secret paths (`~/.ssh`, `.env*`, `*.pem`, `.npmrc`, …) → `SensitivePath`, exit 2.
- `clip` read redacts secret-shaped content (keys/JWTs/tokens) → `redacted:true`.
- `env` redacts by name AND value shape; `dotenv` never reads values at all.
- `http`/`wait -u` refuse cloud metadata endpoints (169.254.169.254 etc.) → `BlockedTarget`;
`http` redacts `set-cookie` response headers.
- `open` allows only http(s)/existing paths; `trash` is reversible and refuses
root/home/cwd; `kill` validates ports and PIDs; `replace` is dry-run unless `--write`.
- Full threat model: SECURITY.md (shipped in this package).
## Notes
- Time/date features are powered by `@master4n/temporal-transformer` v2 (Luxon-backed,
integer epochs; Luxon format tokens, e.g. `yyyy-MM-dd HH:mm:ss`).
- Zero shell interpolation: process/port/package operations use `execFile` (no shell),
so inputs cannot inject commands.
- Time/date powered by `@master4n/temporal-transformer` v2 (Luxon-backed, integer epochs).
- Zero shell interpolation: every subprocess uses `execFile` (no shell) — inputs cannot
inject commands. See SECURITY.md (shipped in this package) for the full threat model.
- `count.tokensEstimate` is a ~4-chars/token heuristic, not a model tokenizer.
{
"name": "@master4n/master-cli",
"version": "3.0.2",
"version": "3.0.3",
"description": "AI-agent-friendly command-line toolkit: timestamp/date conversion, JWT decoding, port killing, file finding, and directory trees — headless, --json, with a self-describing manifest.",

@@ -24,2 +24,6 @@ "type": "module",

"llm-tools",
"llms-txt",
"agent-friendly",
"claude-code",
"coding-agent",
"automation",

@@ -26,0 +30,0 @@ "headless",

+81
-20
# @master4n/master-cli (`mfn`)
[![CI](https://github.com/Master4Novice/master-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/Master4Novice/master-cli/actions/workflows/ci.yml)
[![CodeQL](https://github.com/Master4Novice/master-cli/actions/workflows/codeql.yml/badge.svg)](https://github.com/Master4Novice/master-cli/actions/workflows/codeql.yml)
[![Known Vulnerabilities](https://snyk.io/test/github/Master4Novice/master-cli/badge.svg)](https://snyk.io/test/github/Master4Novice/master-cli)
[![Socket](https://socket.dev/api/badge/npm/package/@master4n/master-cli)](https://socket.dev/npm/package/@master4n/master-cli)
[![npm version](https://img.shields.io/npm/v/%40master4n%2Fmaster-cli)](https://www.npmjs.com/package/@master4n/master-cli)

@@ -9,7 +12,9 @@ ![npm downloads](https://img.shields.io/npm/dm/%40master4n%2Fmaster-cli)

**Master CLI for developers and AI agents.** A set of headless, JSON-first
commands that replace the boilerplate agents otherwise regenerate on every
machine — timestamp/date conversion, JWT decoding, freeing ports, finding files,
and directory trees. Every command runs the same for a human at a terminal and
for an agent reading stdout.
**Master CLI for developers and AI agents.** 43 headless, JSON-first commands in
three families: **token savers** (extract exactly what you need — one JSON field,
a line range, a file outline — instead of dumping whole files into context),
**exact computation** (BigInt math, semver, cron, regex, timezones — verified
answers instead of guesses), and **one-call actions** (free a port, wait for a
server, bulk-replace with dry-run). Every command runs the same for a human at a
terminal and for an agent reading stdout, in ~60ms.

@@ -24,2 +29,15 @@ ## Installation

### Zero-install (agents & one-off use)
No global install needed — `npx` runs any command directly:
```sh
npx -y @master4n/master-cli capabilities --json # discover every command
npx -y @master4n/master-cli epoch 1622547800 --json
```
> **For AI agents:** run `mfn capabilities --json` (or the npx form above) to get
> the machine-readable manifest, and read [`llms.txt`](./llms.txt) — it ships
> inside the npm package and documents the full agent contract.
## The contract (why it's agent-friendly)

@@ -50,22 +68,65 @@

## Commands
## Commands (50)
Run `mfn capabilities` for the grouped list, `mfn <command> --help` for flags.
### OS-level — one call on macOS, Windows, and Linux
| Command | What it does | Example |
| ------- | ------------ | ------- |
| `capabilities` | Self-describing manifest of every command | `mfn capabilities --json` |
| `id` | Generate IDs — UUID v4, time-ordered UUID v7, or URL-safe nano | `mfn id --json` · `mfn id -t uuid7 -n 3 --json` |
| `hash` | Hash a string, file, or stdin (md5/sha1/sha256/sha512) | `mfn hash hello --json` · `mfn hash -f ./x --json` |
| `encode` | Encode/decode text — base64, base64url, hex, url | `mfn encode hi --json` · `mfn encode aGk= -d --json` |
| `random` | Secure random bytes, or an unbiased password | `mfn random --json` · `mfn random -p -l 32 --json` |
| `port` | Find a free port, or check if one is available | `mfn port --json` · `mfn port -c 3000 --json` |
| `epoch` | Convert between epoch timestamps and dates (auto-detects s/ms/µs/ns) | `mfn epoch 1622547800 --json` · `mfn epoch --from 2021-06-01T11:43:20Z --json` |
| `date` | Convert/format a date across timezones (defaults to now) | `mfn date 2024-07-04T15:30:30Z --tz America/New_York --json` |
| `decode` | Decode a JWT (header + payload + expiry; signature **not** verified) | `mfn decode -t <jwt> --json` |
| `kill` | Kill the process(es) listening on given ports | `mfn kill -p 3000 8080 -y --json` |
| `sc` | Fuzzy-find files/folders under the current directory | `mfn sc service --json` |
| `cts` | Print (or export) a tree of the current directory | `mfn cts --json` · `mfn cts -t png` |
| `update` | Update the CLI (or a named package) to the latest version | `mfn update --json` |
| `clip` | Read/write the system clipboard | `git diff \| mfn clip --json` |
| `notify` | Desktop notification — ping the user when a task finishes | `mfn notify "build finished" --json` |
| `open` | Open a file/URL in the default app (validated first) | `mfn open coverage/index.html --json` |
| `procs` | Search processes by name: pid/cpu/mem | `mfn procs node --json` |
| `disk` | Per-mount disk usage without df parsing | `mfn disk --json` |
| `trash` | **Reversible** delete to the OS trash — never `rm -rf` | `mfn trash old-logs --json` |
| `dns` | A/AAAA/CNAME/MX/TXT/NS in one call | `mfn dns github.com --json` |
Run `mfn <command> --help` for the full flag list and more examples.
### Token savers — read less, extract exactly
| Command | What it does | Example |
| ------- | ------------ | ------- |
| `json` | One value from JSON by path — don't read the document | `mfn json scripts.build -f package.json --json` |
| `schema` | Infer JSON shape (paths + types); 10MB payload → ~20 lines | `mfn schema -f response.json --json` |
| `count` | Lines/words/chars/bytes + **LLM token estimate** | `git diff \| mfn count --json` |
| `lines` | Exact line range of a file (1-based), never the whole file | `mfn lines src/app.ts -s 120 -n 30 --json` |
| `outline` | Symbols + line numbers (.ts .js .py .go .md) | `mfn outline src/app.ts --json` |
| `diff` | Structured hunks of two files, counts first | `mfn diff old.json new.json -s --json` |
| `freq` | Most repeated lines — log triage in one call | `mfn freq error.log -t 5 --json` |
| `imports` | A file's imports, or who imports a module | `mfn imports --who utility --json` |
| `repo` | Git branch/dirty/ahead-behind/commits in one object | `mfn repo --json` |
| `sys` / `have` / `ip` | System facts · tool versions · local addresses | `mfn have node git docker --json` |
| `size` / `ext` / `recent` | Disk usage · composition by extension · newest files | `mfn size -t 5 --json` |
| `ports` | ALL listening TCP ports with owning processes | `mfn ports --json` |
| `pkg` | Declared vs installed dependency versions | `mfn pkg --json` |
| `env` / `dotenv` | Env inspection (secrets **always** redacted) · .env completeness | `mfn dotenv --json` |
### Exact computation — never guess
| Command | What it does | Example |
| ------- | ------------ | ------- |
| `calc` | BigInt-exact arithmetic — `2^53 + 1` comes out right | `mfn calc "2^53 + 1" --json` |
| `base` | hex/dec/bin/oct conversion, BigInt-safe | `mfn base 0xff --json` |
| `semver` | Validate/compare/sort/bump per semver.org | `mfn semver 1.10.0 1.9.2 --json` |
| `cron` | Validate + explain + next run times | `mfn cron "*/15 9-17 * * 1-5" --json` |
| `regex` | Test a pattern — matches with line/index/groups | `mfn regex "TODO" -f src/app.ts --json` |
| `url` | URL → components + decoded query params | `mfn url "https://x.com/a?b=1" --json` |
| `escape` | Context-exact escaping: shell, JSON, regex, HTML, URL | `mfn escape "it's" --json` |
| `case` | camel/snake/kebab/pascal/… conversion | `mfn case getUserName -t snake --json` |
| `epoch` / `date` | Epoch ↔ date (auto unit) · timezone conversion | `mfn epoch 1622547800 --json` |
| `decode` | JWT header + payload + expiry (signature not verified) | `mfn decode -t <jwt> --json` |
### Actions — do, don't script
| Command | What it does | Example |
| ------- | ------------ | ------- |
| `replace` | Literal find/replace across files — **dry-run by default** | `mfn replace old new -g "src/**/*.ts" --json` |
| `wait` | Block until port/URL/file is ready — no sleep loops | `mfn wait -p 3000 -t 30 --json` |
| `kill` | Free the ports your dev server got stuck on | `mfn kill -p 3000 8080 -y --json` |
| `http` | Probe a URL: status/headers/timing, capped body preview | `mfn http localhost:3000/health --json` |
| `port` | Find a free port, or check one | `mfn port -c 3000 --json` |
| `id` / `hash` / `encode` / `random` | UUID v4/v7/nano · digests · codecs · CSPRNG | `mfn id -t uuid7 -n 3 --json` |
| `sc` / `cts` | Fuzzy file find · directory tree | `mfn sc service --json` |
| `capabilities` / `update` | Machine-readable manifest · self-update | `mfn capabilities --json` |
### Examples

@@ -72,0 +133,0 @@

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display