You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Two agent-first CLI spec adoptions from cli-specs.intrane.fr:
## secure guide (cli-guide-spec v1.0)
The embedded mental model: model, loop, concepts, commands, examples, gotchas.
JSON by default (agent-first), --human for readable markdown. Embedded in the
binary — no network fetch. A pure-CLI tool conforms without HTTP endpoints.
An agent that lands on a fresh machine with only the binary reads `secure guide`
once and drives the tool with no external docs. This is the mental model that
--help (the command catalog) cannot be.
Body shape per spec §1: one_liner, model, loop, concepts, commands, examples,
gotchas, version, see_also. Advertised in --help.
## secure feedback (cli-feedback-spec v1.0)
Relay-only feedback: best-effort POST to https://feedback.intrane.fr/v1/feedback,
tagged app=machin-secure. Never fails the caller (exit 0 even if relay is down).
FEEDBACK_RELAY=off disables. Client-generated idempotency key (8 random bytes hex).
Like remotecmd, machin-secure is a peer tool with no local feedback endpoint, so
it adopts the relay-only variant of the spec (§3: skip local write, keep relay write).
Usage:
secure feedback "<message>" [--kind bug|idea|praise|note] [--context "<what you were doing>"]
Verified:
- guide: valid JSON with all spec fields (one_liner, model, loop, concepts,
commands, examples, gotchas, version, see_also)
- guide --human: readable markdown rendering
- guide --help: usage
- feedback: relayed:1 with real relay, relayed:0 with FEEDBACK_RELAY=off
- feedback: never fails (exit 0 even when relay unreachable)
- feedback: empty message → error exit 1
- --help advertises both subcommands
- 1861 findings byte-identical on test/fixtures (no scan regression)
Reference implementations: grepapi (machin, JSON agent-skill), remotmd (Go,
relay-only feedback). machin-secure is now listed as a conforming tool for both
specs.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
// JSON by default (agent-first); --human for readable markdown. Embedded in the
995
+
// binary — no network fetch. A pure-CLI tool conforms without HTTP endpoints.
996
+
997
+
func guide_json() (g) {
998
+
g = "{"
999
+
g = g + "\"machin-secure\":\"a free, deterministic, agent-first security scanner (1000 rules, 25 languages, SARIF to GitHub)\","
1000
+
g = g + "\"one_liner\":\"A regex-based SAST that runs in your CI on every push for free — no per-developer seat tax, no LLM API calls, your code never leaves your runner. The scan loop is deterministic; the judgment (triage, false-positive suppression) is BYOK — your agent or your engineer decides, and the tool persists the verdict.\","
1001
+
g = g + "\"model\":{"
1002
+
g = g + "\"split\":\"DETERMINISTIC SCAN LOOP (regex rules, no API calls, free, every push) / BYOK JUDGMENT (your agent or engineer triages findings, files verdicts and suppression patterns that persist across scans). The tool never calls an LLM — the CLI is the agent interface.\","
1003
+
g = g + "\"byok_llm\":\"the operator IS the LLM. secure emits structured findings (JSONL); YOUR agent reads them, judges them, and writes back verdicts via `secure verdict` / `secure suppress`. No API key, no token billing, no network call to a model provider.\","
1004
+
g = g + "\"no_server\":\"pure CLI — no server, no database, no index. The filesystem is scanned fresh every time. The only state that persists is the verdict store and the patterns store (the agent's own memory, not a cache the tool invents).\","
1005
+
g = g + "\"sarif\":\"--sarif emits a SARIF 2.1.0 report for GitHub Code Scanning / the Security tab. JSONL is the default for agent consumption; SARIF is for CI integration.\"},"
1006
+
g = g + "\"loop\":["
1007
+
g = g + "\"secure --target . --diff-base origin/main --pending --context 3 # scan changed files, only unreviewed findings, with ±3 lines of context\","
1008
+
g = g + "\"# agent reads the findings JSONL, applies judgment (keep/drop/suppress pattern)\","
1009
+
g = g + "\"secure verdict --stdin < batch_of_keep_drop.jsonl # persist individual verdicts\","
1010
+
g = g + "\"secure suppress --rule X --glob '*.vue' --reason 'Vue prop bindings' # persist a pattern for repeated false positives\","
1011
+
g = g + "\"# next scan: --pending shows only genuinely new findings — suppressed ones stay suppressed\","
1012
+
g = g + "\"# for CI: secure --sarif --diff-base origin/main > results.sarif && upload to GitHub Security tab\"],"
1013
+
g = g + "\"concepts\":{"
1014
+
g = g + "\"finding\":\"a JSONL object: {id, rule, file, line, severity, cwe, message, snippet, verdict, ctx_before, ctx_after}. The id is a stable SHA-256 of (rule|file|trimmed_line) — pass it to `secure verdict`.\","
1015
+
g = g + "\"verdict\":\"the agent's judgment on a specific finding id: 'keep' (confirmed real) or 'drop' (false positive). Dropped findings are suppressed in future scans. Stored in .machin-secure.verdicts.json.\","
1016
+
g = g + "\"suppress_pattern\":\"a rule-level false-positive filter: (rule, glob) → suppress. Instead of dropping 30 individual findings from the same rule on *.vue files, file one pattern and they stay dropped. Stored in .machin-secure.patterns.json.\","
1017
+
g = g + "\"pending\":\"--pending emits only unreviewed findings (verdict == \\\"\\\"), excluding both keep and drop. The agent's work queue — what's new since last triage.\","
1018
+
g = g + "\"context\":\"--context N emits ±N lines of code around each finding as ctx_before/ctx_after arrays, so the agent can triage without a read_file round-trip per finding.\","
1019
+
g = g + "\"diff_base\":\"--diff-base REF scans only files changed vs REF (git diff --name-only REF...HEAD). For CI/PR-scoped scans — fast feedback on what changed.\","
1020
+
g = g + "\"literal_prefilter\":\"each rule has a required literal substring extracted at load time; the scan loop does a cheap contains() before the expensive regex_match. 5.8x speedup on large files, byte-identical findings.\"},"
g = g + "\"verdict\":[\"secure verdict --target . <id> <keep|drop> [--reason TEXT]\",\"secure verdict --target . --stdin < batch.jsonl\"],"
1024
+
g = g + "\"suppress\":[\"secure suppress --target . --rule RULE --glob GLOB [--reason TEXT]\",\"secure suppress --target . --stdin < batch.jsonl\"],"
1025
+
g = g + "\"introspection\":[\"secure guide\",\"secure guide --human\",\"secure --help\",\"secure feedback \\\"<message>\\\" [--kind bug|idea|praise|note]\"]},"
1026
+
g = g + "\"examples\":["
1027
+
g = g + "{\"goal\":\"scan a PR for new findings\",\"do\":[\"secure --target . --diff-base origin/main --pending --context 3\",\"# agent triages the findings\",\"secure verdict --stdin < keep_drop_batch.jsonl\"]},"
1028
+
g = g + "{\"goal\":\"suppress repeated false positives from one rule\",\"do\":[\"secure suppress --target . --rule js-hardcoded-secret --glob '*.vue' --reason 'Vue prop bindings, not secrets'\",\"secure --target . --pending # those findings no longer appear\"]},"
1029
+
g = g + "{\"goal\":\"CI: SARIF to GitHub Security tab\",\"do\":[\"secure --target . --diff-base origin/main --sarif > results.sarif\",\"# upload results.sarif via github/codeql-action/upload-sarif\"]},"
1030
+
g = g + "{\"goal\":\"full audit of a repo\",\"do\":[\"secure --target . --context 3 # all findings, with code context\",\"secure --target . --summary # just the counts\"]}],"
1031
+
g = g + "\"gotchas\":["
1032
+
g = g + "\"POSIX ERE only — no PCRE features like (?!...) lookahead; they silently no-op\","
1033
+
g = g + "\"\\\\d is NOT supported in POSIX ERE (silently fails to match) — use [0-9] instead; \\\\b, \\\\s, \\\\w DO work\","
1034
+
g = g + "\"the tool never calls an LLM — the agent does all triage; the CLI is the agent interface (grepapi split)\","
1035
+
g = g + "\"verdicts and patterns are per-repo (.machin-secure.verdicts.json / .machin-secure.patterns.json) — commit them to share triage across the team\","
1036
+
g = g + "\"--pending takes precedence over --show-all (even with show-all, pending excludes reviewed findings)\","
1037
+
g = g + "\"exit codes: 0 = clean, 1 = error, 2 = high/critical findings present\","
1038
+
g = g + "\"stdout = data (JSONL/SARIF/summary), stderr = nothing or logs — pipe-friendly\","
1039
+
g = g + "\"the scan loop is regex SAST, not taint tracking — use CodeQL for data-flow analysis (it's free for public repos)\"],"
1040
+
g = g + "\"version\":\"" + version + "\","
1041
+
g = g + "\"see_also\":[\"secure --help\",\"secure feedback --help\"]"
1042
+
g = g + "}"
1043
+
}
1044
+
1045
+
func guide_human() (h) {
1046
+
h = "# machin-secure — agent-first security scanner\n\n"
1047
+
h = h + "A free, deterministic, regex-based SAST: 1000 rules, 25 languages, SARIF to GitHub.\n"
1048
+
h = h + "The scan loop is deterministic and free; the judgment is BYOK — your agent decides.\n\n"
1049
+
h = h + "## The model\n\n"
1050
+
h = h + "- **Deterministic scan loop**: regex rules, no API calls, runs in CI on every push for free.\n"
1051
+
h = h + "- **BYOK judgment**: your agent or engineer triages findings, files verdicts and suppression\n"
1052
+
h = h + " patterns that persist across scans. The tool never calls an LLM.\n"
1053
+
h = h + "- **No server**: pure CLI, no database, no index. Filesystem scanned fresh every time.\n"
1054
+
h = h + "- **SARIF**: --sarif for GitHub Code Scanning; JSONL (default) for agent consumption.\n\n"
1055
+
h = h + "## The loop\n\n"
1056
+
h = h + "1. `secure --target . --diff-base origin/main --pending --context 3`\n"
1057
+
h = h + " → only new findings in changed files, each with ±3 lines of context\n"
1058
+
h = h + "2. agent reads findings, applies judgment (keep/drop/suppress pattern)\n"
1059
+
h = h + "3. `secure verdict --stdin < batch.jsonl` → persist individual verdicts\n"
1060
+
h = h + "4. `secure suppress --rule X --glob '*.vue' --reason '...'` → persist a pattern\n"
1061
+
h = h + "5. next scan: --pending shows only genuinely new findings\n\n"
1062
+
h = h + "## Commands\n\n"
1063
+
h = h + "- `secure --target . [flags]` — scan (JSONL by default)\n"
1064
+
h = h + "- `secure verdict <id> <keep|drop>` — persist a finding verdict\n"
1065
+
h = h + "- `secure suppress --rule R --glob G` — persist a suppression pattern\n"
1066
+
h = h + "- `secure guide [--human]` — this guide\n"
1067
+
h = h + "- `secure feedback \"<message>\"` — send feedback to the maintainer\n\n"
1068
+
h = h + "## Key flags\n\n"
1069
+
h = h + "- `--pending` — only unreviewed findings (verdict == \"\")\n"
1070
+
h = h + "- `--context N` — ±N lines of code around each finding\n"
1071
+
h = h + "- `--diff-base REF` — scan only files changed vs REF\n"
1072
+
h = h + "- `--sarif` — SARIF 2.1.0 output for GitHub Security tab\n"
1073
+
h = h + "- `--show-all` — include suppressed findings\n\n"
1074
+
h = h + "## Gotchas\n\n"
1075
+
h = h + "- POSIX ERE only — no `(?!...)` lookahead, no `\\d` (use `[0-9]`)\n"
1076
+
h = h + "- The tool never calls an LLM — the agent does all triage\n"
1077
+
h = h + "- Verdicts/patterns are per-repo — commit them to share across the team\n"
1078
+
h = h + "- Exit codes: 0 = clean, 1 = error, 2 = high/critical findings present\n"
1079
+
h = h + "- Regex SAST, not taint tracking — use CodeQL for data-flow analysis\n\n"
1080
+
h = h + "Version: " + version + "\n"
1081
+
}
1082
+
1083
+
func cmd_guide(a) {
1084
+
want_human := false
1085
+
help := false
1086
+
i := 2
1087
+
for i < len(a) {
1088
+
arg := a[i]
1089
+
if arg == "--human" { want_human = true }
1090
+
if arg == "--help" || arg == "-h" { help = true }
1091
+
i = i + 1
1092
+
}
1093
+
if help {
1094
+
println("usage: secure guide [--human]")
1095
+
println("")
1096
+
println("Prints the embedded agent skill: the model, the loop, concepts, commands,")
1097
+
println("examples, and gotchas. JSON by default (agent-first); --human for readable")
1098
+
println("markdown. Embedded in the binary — no network fetch.")
1099
+
println("")
1100
+
println("An agent that lands on a fresh machine with only the binary reads this once")
1101
+
println("and drives the tool with no external docs. This is the mental model that")
1102
+
println("--help (the command catalog) cannot be.")
0 commit comments