fremforge CLI
fremforge CLI är en fristående binär som omsluter det offentliga REST API:t. Samma verb, samma behörighetsmodell, samma scopes. Distribueras enbart från PoP:ar i EU; inget npm-register, ingen Docker Hub, inget beroende av Sigstore Fulcio.
Supportperiod, säkerhetsuppdateringar och SBOM
| Supportperiod | 5 år från lanseringsdatumet för varje minor-version. Det är supportperioden i den mening som avses i artikel 13.8 i Cyberresiliensförordningen (förordning (EU) 2024/2847), och den är knuten till den släppta versionen, inte till din prenumeration. |
| Säkerhetsrättningar | Kostnadsfria, alltid, och aldrig låsta bakom en plan. Rättningar levereras framåt som en ny release på samma URL:er, täckta av samma signerade SHA256SUMS. Kör du en ersatt version? Uppgradera för att få rättningen. |
| Rapportera en sårbarhet | security@frem.sh: samordnat avslöjande, detaljer på www.frem.sh/security. |
| SBOM | CycloneDX JSON på cli.frem.sh/cli/SBOM.cdx.json, per version på cli.frem.sh/cli/v<version>/SBOM.cdx.json. |
| Avtalsvillkor | Användarvillkoren §7.5: licens, garanti och ansvar specifikt för binären. |
SBOM:en är kort, och det är hela poängen. CLI:t deklarerar noll npm-beroenden från
tredje part. Det har två beroenden, båda våra egna: @fremverk/audit-chain, samma
hashkedjekod som API:t självt kör (delad i stället för omimplementerad så att audit-verify
inte kan glida isär från det den verifierar), och @fremforge/tlog-verify, som kontrollerar
inkludering i transparensloggen för attest-verify. Inget av dem har egna beroenden; båda
importerar bara Nodes inbyggda moduler, så hela ytan från tredje part i den levererade
binären är Bun-körtiden som bäddas in vid kompileringen. Från v0.3.1 listar SBOM:en även de
två förstapartspaketen, markerade som våra, så att den namnger varje komponent och inte bara
den från tredje part.
SBOM:ens hash finns i SHA256SUMS, så den täcks av samma Ed25519-signatur som binärerna.
Verifiera den på samma sätt (se §”Verifiera Ed25519-signaturen”
nedan; det gäller varje fil som listas i manifestet, inte bara binärerna):
curl -fsSL https://cli.frem.sh/cli/SBOM.cdx.json -o SBOM.cdx.json
curl -fsSL https://trust.frem.sh/SHA256SUMS -o SHA256SUMS
grep SBOM.cdx.json SHA256SUMS | shasum -a 256 -c -CLI:t är valfritt, med ett undantag. Varje åtgärd det utför finns tillgänglig via
REST API:t, så om din policy är att inte köra leverantörers binärer förlorar
du ingen funktionalitet på att avstå. Undantaget är audit-verify, som räknar om din
granskningshashkedja på din egen dator. Det kan ett API inte göra åt dig, eftersom hela
poängen med att räkna om en hashkedja är att inte lita på den part som har tagit fram den. De
råa raderna tillhandahålls av GET /orgs/{org}/audit/chain, så du kan göra
beräkningen i dina egna verktyg i stället; det du inte kan göra är att låta oss göra den och
kalla resultatet för verifiering.
Installera
En rad (rekommenderas)
curl -sSfL https://cli.frem.sh/cli/install.sh | shInstallationsprogrammet identifierar automatiskt ditt operativsystem (Linux eller macOS) och din arkitektur (arm64 eller x86_64), laddar ned motsvarande binär från https://cli.frem.sh/cli/, laddar ned den kanoniska SHA256SUMS från https://trust.frem.sh/ (en separat värd med en separat skrivbehörighet, så att ett intrång enbart på binärvärden inte kan förfalska en matchning), verifierar SHA-256 och installerar till ~/.local/bin/fremforge eller /usr/local/bin/fremforge.
Ändra installationsplatsen med FREMFORGE_INSTALL_DIR:
curl -sSfL https://cli.frem.sh/cli/install.sh | FREMFORGE_INSTALL_DIR=/opt/fremforge/bin shLås en viss version:
curl -sSfL https://cli.frem.sh/cli/install.sh | FREMFORGE_VERSION=0.1.0 shManuell nedladdning
Om du helst inte vill skicka ett fjärrskript direkt till sh går binärerna att nå direkt. Välj det par som passar:
| OS | Arkitektur | URL |
|---|---|---|
| macOS | arm64 | https://cli.frem.sh/cli/fremforge-darwin-arm64 |
| macOS | x86_64 | https://cli.frem.sh/cli/fremforge-darwin-x64 |
| Linux | arm64 | https://cli.frem.sh/cli/fremforge-linux-arm64 |
| Linux | x86_64 | https://cli.frem.sh/cli/fremforge-linux-x64 |
| Windows | x86_64 | https://cli.frem.sh/cli/fremforge-windows-x64.exe |
Arkitektursuffixet är x64 (inte x86_64) och arm64; de motsvarar Buns --target-token. uname -m rapporterar x86_64 på Intel/AMD, så översätt det till x64 när du bygger URL:en för hand (installationsraden gör det åt dig).
Verifiera mot den kanoniska hashen på trust.frem.sh innan du kör binären:
# 0. Map uname -m's x86_64 to the published x64 token
arch=$(uname -m); [ "$arch" = x86_64 ] && arch=x64
# 1. Download the binary
curl -fsSL https://cli.frem.sh/cli/fremforge-$(uname -s | tr A-Z a-z)-$arch \
-o fremforge
# 2. Download the canonical SHA256SUMS (separate host, separate credential)
curl -fsSL https://trust.frem.sh/SHA256SUMS -o SHA256SUMS
# 3. Verify
sha256sum --check --ignore-missing SHA256SUMS
# 4. Install
chmod +x fremforge
sudo install -m 0755 fremforge /usr/local/bin/fremforgeVerifiera Ed25519-signaturen (valfritt, rekommenderas)
Utöver SHA-256-matchningen signeras varje release som ett DSSE-inslaget in-toto-uttalande under samma förtroenderot som fremforges SLSA-byggproveniens. Verifieraren laddar ned den publika förtroenderoten från www.frem.sh/.well-known/slsa-trust-root.json och kontrollerar Ed25519-signaturen på bytena i SHA256SUMS.
Använd inte
slsa-verifier verify-artifact. Det underkommandot saknar flaggan--trusted-root, och det kan varken läsa fremforges JSON-förtroenderot eller ett DSSE-kuvert med ren Ed25519; det förväntar sig ett paket i Sigstore-stil. Den här sidan visade tidigare ett sådant kommando; det hade aldrig kunnat köras. Verifiera direkt i stället, med verktyg som din distribution redan har.
SHA256SUMS.intoto.jsonl är JSON Lines: ett DSSE-kuvert per publicerad binär. Verifiera
varje rad du bryr dig om.
# Pull the trust root and the signed envelopes
curl -fsSL https://www.frem.sh/.well-known/slsa-trust-root.json -o slsa-trust-root.json
curl -fsSL https://trust.frem.sh/SHA256SUMS.intoto.jsonl -o SHA256SUMS.intoto.jsonl
# Extract the builder public key: v2, the active key since 2026-09-12. An envelope's
# .signatures[0].keyid names its key; one signed before 2026-09-12 needs ...-v1.
jq -r '.trusted_keys[] | select(.kid=="fremforge-slsa-builder-v2") | .pem' \
slsa-trust-root.json > builder.pub
# Verify every envelope: rebuild the DSSE pre-authentication encoding and check it
while read -r line; do
pt=$(printf '%s' "$line" | jq -r .payloadType)
printf '%s' "$line" | jq -r .payload | base64 -d > payload.bin
printf '%s' "$line" | jq -r '.signatures[0].sig' | base64 -d > sig.bin
{ printf 'DSSEv1 %s %s %s ' "${#pt}" "$pt" "$(wc -c < payload.bin)"; cat payload.bin; } > pae.bin
openssl pkeyutl -verify -pubin -inkey builder.pub -rawin -in pae.bin -sigfile sig.bin \
&& jq -r '.subject[] | .name + " " + .digest.sha256' payload.bin
done < SHA256SUMS.intoto.jsonlVarje verifierat kuvert skriver ut alla artefakter det täcker och den digest som fremforge signerade för var och en. Jämför den digesten med binären du laddade ned; det är den jämförelsen som är poängen, signaturen talar bara om att digesten kommer från oss.
Förtroenderoten är densamma som används för byggproveniens på artefakter som din runner producerar: samma Ed25519-nyckel, samma builderId, samma verifieringsrecept. Vi anger ingen SLSA-nivå; säkerhetssidan förklarar varför.
Autentisering
CLI:t stöder tre sätt att ange inloggningsuppgifter, som avgörs i den här ordningen: flaggan --token=…, miljövariabeln FREMFORGE_TOKEN och sedan den sparade inloggningen i ~/.config/fremforge/auth.json.
Rekommenderas: inloggning i webbläsaren (inget att klistra in)
fremforge auth loginÖppnar webbläsaren mot frem.sh, du godkänner enheten, token hamnar i ~/.config/fremforge/auth.json (läge 600) och laddas sedan automatiskt vid varje anrop. Det är samma OAuth2 + PKCE-flöde som din git push redan använder, så om du återkallar token på frem.sh/user/settings/applications återkallas både git-åtkomsten och CLI-åtkomsten i ett steg.
fremforge auth status # show current login + expiry
fremforge auth logout # revoke + delete the local fileToken fungerar mot både fremforges REST API (/_app/api/v1/orgs/…) OCH Forgejos eget API (/api/v1/repos/…): Forgejo accepterar sina egna OAuth-bearer-token direkt, och fremforges API validerar dem via introspektion mot Forgejos /api/v1/user. Samma identitet, båda ytorna.
CI och skript: PAT
För icke-interaktiva sammanhang (CI-jobb, skript, agenter), skapa en PAT med avgränsade scopes. Enklast är att använda CLI:t självt när du väl har loggat in interaktivt en gång (fremforge auth tokens create --name=… --scopes=…; se Skapa en avgränsad PAT för CI), eller skapa en på https://frem.sh/user/settings/applications. Sedan:
export FREMFORGE_TOKEN='<your PAT>'
fremforge whoamiÄndra bas-URL:en med FREMFORGE_URL= (måste vara HTTPS); standard är https://frem.sh.
Kommandon
fremforge auth login Browser-based OAuth2+PKCE login.
fremforge auth logout Revoke + delete the stored token.
fremforge auth status Show current login + expiry.
fremforge whoami Print the user the token authenticates as.
fremforge data-export start <slug> Queue a full data export for the org.
fremforge data-export list <slug> List recent export jobs.
fremforge dependency-updates enable <slug> Enable hosted Renovate for the org.
fremforge dependency-updates disable <slug> Disable hosted Renovate for the org.
fremforge dependency-updates run-now <slug> Trigger an out-of-cycle Renovate run (1/h cap).
fremforge audit-log <slug> Fetch the org audit-log slice.
[--since=DATE] [--actor=…] [--action=…] [--limit=N]
fremforge audit-verify <slug> RECOMPUTE the per-tenant audit hash chain
[--human] [--full] locally, then cross-check our own verdict.
Exit 0=ok, 2=partial, 3=broken,
4=anchor_mismatch, 5=local ok but we
disagreed. --full walks from the chain
epoch instead of the latest anchor.
fremforge sbom <owner>/<repo> <tag> Download a release SBOM.
[--format=spdx|cyclonedx]
fremforge runs <owner>/<repo> List recent CI runs (JSON; --human for a table).
[--limit=N] [--status=…] [--event=…]
fremforge runs logs <owner>/<repo> <run-id> Fetch a run's logs (text/plain, all jobs).
fremforge auth tokens create Mint a scoped PAT (printed once).
--name=N --scopes=a,b [--ttl-days=N]
fremforge auth tokens list List your PATs (--human for a table).
fremforge auth tokens revoke <token-id> Revoke a PAT.
fremforge findings <type> <slug> Security findings. type ∈ secrets |
[--status=…] [--repo=…] dependencies | signed-commits | attestations.
fremforge secrets list <slug> List org Actions/CI secret names.
fremforge secrets set <slug> <NAME> Set a secret (value via FREMFORGE_SECRET_VALUE).
fremforge secrets delete <slug> <NAME> Delete a secret.
fremforge seats list <slug> List org members + seat usage.
fremforge seats add <slug> --email=E Add a member (--username=, --full-name= optional).
fremforge seats remove <slug> <username> Remove a member.
fremforge work start <org>/<repo> Declare work before the first push (Active work).
--title=TEXT [--intent=TEXT] Prints the branch to create and related work.
[--areas=a,b] [--branch=NAME]
fremforge work list <org>/<repo> Who is building what in a repository.
[--area=AREA]
fremforge version Print the CLI version.Kör fremforge --help för den kanoniska referensen, eller lägg till --human på de kommandon som stöder det för utdata formaterad som tabell.
Exempel
Verifiera din granskningskedja själv (använd i CI)
audit-verify frågar inte oss om din granskningslogg är intakt. Det laddar ned de råa raderna,
räknar om varje hash och varje länk på din dator, och jämför först därefter sitt resultat
med vårt. Avslutskoden är ditt resultat, inte vårt påstående, och om de två inte stämmer
överens rapporteras själva oenigheten och kommandot misslyckas.
Den skillnaden är skälet till att kommandot finns. Fram till augusti 2026 läste det fältet
integrity_status ur ett API-svar och översatte det till en avslutskod, vilket innebar att den
part som granskades räknade ut svaret och ”verifieringsverktyget” bara förde det vidare.
Ingenting du kunde köra skulle ha upptäckt ett komprometterat eller oärligt API. Nu gör något
det.
export FREMFORGE_TOKEN='<your PAT, audit:read scope>'
# Human-readable, for terminals
fremforge audit-verify acme --human
# Script-friendly. The exit code reflects the LOCAL walk:
# 0 = ok
# 2 = partial — some of the chain could not be checked (see below)
# 3 = broken — a row's content or its link does not match. Investigate.
# 4 = anchor_mismatch — the WORM-anchored tip is not present in your chain
# 5 = we disagreed — your walk was clean but our verdict was not
# 6 = bad signature — the anchor's signature failed against our published key
fremforge audit-verify acme || {
echo "audit verification failed with exit code $?"
exit 1
}
# Walk the entire chain from its first row instead of just the tail since the
# last anchor. Slower and much larger; appropriate for a quarterly review.
fremforge audit-verify acme --full --humanLäs resultaten ärligt, eftersom ett verifieringsverktyg som överdriver sin egen förmåga är värre än inget alls:
partialär inte godkänt. Det betyder att trunkering har dolt en del av kedjan, så raderna utanför fönstret är overifierade. Vi rapporteraroki det fallet, och CLI:t gör medvetet inte det.- Raderade och maskerade rader stämmer inte med sin hash, avsiktligt. GDPR-radering och
rensningen av nyttolaster efter 90 dagar skriver om radernas innehåll i efterhand, så de
raderna stämmer inte längre med sin egen hash. De räknas separat
(
tenant_erased_count,payload_redacted_count) och är inte manipulation. Deras länkar kontrolleras fortfarande. - WORM-ankaret är signerat, och CLI:t kontrollerar det mot en förtroenderot som det hämtar
själv.
audit-verifyhämtarwww.frem.sh/.well-known/slsa-trust-root.jsondirekt, aldrig en nyckel från API:t, verifierar Ed25519-DSSE-signaturen och bekräftar att kuvertet är bundet till just det här ankaret och inte till något annat. Avslutskod 6 betyder att signaturen kontrollerades och inte godkändes; behandla det som en incident.NOT CHECKED(avslutskoden oförändrad) betyder antingen att ankaret är äldre än signeringen (2026-08-04) eller att förtroenderoten inte gick att nå från din dator. Inget av det är ett fel, och CLI:t säger vilket det är.
För att göra samma sak utan binären, läs raderna från
GET /orgs/{org}/audit/chain och hasha varje rads kanoniska JSON med
nycklarna ordnade action, actor, created_at_iso, fields_json, prev_hash, tenant_id. Behåll
fields_json byte för byte: tolka och serialisera inte om det, annars stämmer inte dina
digester.
Se granskningskedjans integritet för hela garantin.
Dataexport med självbetjäning
# Kick off
fremforge data-export start acme | jq .
# Poll
fremforge data-export list acme | jq '.[] | {id, status, created_at}'Se dataexport för artefaktformatet, lagringstiden och nedladdningsflödet med signerad URL.
Beroendeuppdateringar (hostad Renovate)
fremforge dependency-updates enable acme
fremforge dependency-updates run-now acme # 1/h rate-limit appliesSe beroendeuppdateringar för vad som tas med och hur du avgränsar det per repo.
Nedladdning av SBOM
fremforge sbom acme/api v1.4.0 --format=spdx > sbom.spdx.json
fremforge sbom acme/api v1.4.0 --format=cyclonedx > sbom.cyclonedx.jsonUtdrag ur granskningsloggen
fremforge audit-log acme --since=2026-05-01 --action=push-protection-override | jq .CI-körningar och loggar
Lista de senaste körningarna och hämta sedan en körnings fullständiga loggar (alla jobb sammanslagna) via dess globala körnings-id:
# List the 20 most recent runs as a table
fremforge runs acme/api --human
# Script-friendly: grab the newest run id, then fetch its logs
run_id=$(fremforge runs acme/api --limit=1 | jq -r '.workflow_runs[0].id')
fremforge runs logs acme/api "$run_id"
# Tail just the failing step
fremforge runs logs acme/api "$run_id" | grep -iE "error|failed|exit code" | tail<run-id> är det globala körnings-id som fremforge runs visar (fältet .workflow_runs[].id), inte körningsnumret per arbetsflöde i webbgränssnittets URL. Logg-endpointen returnerar text/plain med alla jobb i ett och samma svar; ingen nedladdning av artefakter per jobb behövs.
Skapa en avgränsad PAT för CI
Efter din första fremforge auth login kan du skapa undertoken med snäva scopes för CI utan att lämna terminalen. Token skrivs ut en gång, så spara den direkt:
fremforge auth tokens create --name=ci-readonly --scopes=findings:read,orgs:read --ttl-days=30 \
| jq -r .token
fremforge auth tokens list --human
fremforge auth tokens revoke <token-id>Du kan bara ge scopes som din egen token redan har, och jokertecknet (*) kan inte användas här.
Hantera CI-secrets
fremforge secrets list acme
# Pass the value via env (preferred — not in shell history or `ps`)
FREMFORGE_SECRET_VALUE="$(cat ./deploy-key)" fremforge secrets set acme DEPLOY_KEY
fremforge secrets delete acme OLD_TOKENAnvändare och medlemmar
fremforge seats list acme --human # cap + usage + roster
fremforge seats add acme --email=jane@acme.example --full-name="Jane Doe"
fremforge seats remove acme janeOm du lägger till en medlem över det avtalade taket för antal användare får du 409 med en länk till faktureringen. Köp fler användare först.
Utdataformat
Som standard skriver varje kommando JSON till stdout, lämpligt för skript och pipes. Ange --human på de kommandon som stöder det (audit-verify, attest-verify, release verify, runs, auth tokens list, seats list och work) för en formaterad sammanfattning.
Uppdatera CLI:t
Installationsraden är idempotent: kör du den igen hämtas den senaste binären, kontrollsumman verifieras på nytt och den gamla binären skrivs över på plats:
curl -sSfL https://cli.frem.sh/cli/install.sh | shOm suveränitet
CLI:ts distributionsväg är helt EU-suverän:
- Binärer: T Cloud Public OBS (eu-de, Magdeburg/Biere, Tyskland), bakom en Bunny-pull-zon som är begränsad till PoP:ar i EU.
- SHA256SUMS + DSSE-kuvert: en separat OBS-bucket i T Cloud Public (
trust.frem.sh) med en separat skrivbehörighet. Att binärvärden är skild från integritetsvärden betyder att ett intrång i den ena inte kan förfalska en matchning mot den andra. - Förtroenderot: en statisk JSON-fil som serveras från
www.frem.sh(samma Bunny-routning enbart inom EU). - Inget beroende av npm-registret: registry.npmjs.com körs i AWS i USA; CLI:t rör det aldrig, varken vid installation eller användning.
- Inget beroende av Docker Hub: av samma skäl.
- Ingen Sigstore Fulcio/Rekor: Sigstores transparenslogg ligger i USA. fremforge kör en egen Ed25519-signerare och en statisk förtroenderot i stället för att vara beroende av Fulcio.
Underbiträden som berörs på installationsvägen listas i det offentliga registret över underbiträden och är samma som redan omfattar kundens personuppgifter enligt DPA:ns bilaga B.