Kommandolinje
pfmem
En klient i én fil til hukommelses-API'et, skrevet til at blive styret af en AI-harness. Den holder én nøgle og kalder hukommelsesendpointsene. Den kan ikke udstede, rotere eller tilbagekalde en nøgle, oprette et arbejdsområde eller konfigurere en udbyder — det er administration, og det ligger bag admin-API'et med vilje.
Installation
Installationsprogrammet henter det offentliggjorte manifest, downloader bundtet, verificerer det mod manifestets sha256 og installerer en launcher. Der kompileres intet, og der kræves ingen root.
curl -fsSL https://pfmem-api.packagefactory.dk/install.sh | sh
pfmem initDet kræver curl, Node 22 eller nyere, mktemp og sed, og det siger hvilket af dem, der mangler, frem for at fejle senere med en syntaksfejl.
To miljøvariabler flytter installationen: den ene flytter det hele, den anden peger den mod et andet deployment.
PFMEM_HOME="$HOME/.local/pfmem"
PFMEM_ORIGIN="https://pfmem-api.packagefactory.dk"Kontrakten om stdout
Den primære kalder er en model, så standard output er altid præcis ét JSON-dokument. Alt, der er skrevet til et menneske — prompts, advarsler, opdateringsbeskeder — går til standard error, hvor en parser aldrig ser det.
{"ok":true,"request_id":"…","data":{…}}
{"ok":false,"error":{"code":"…","message":"…","request_id":"…"}}Se på ok-flaget først. Ved en fejl skal du forgrene på fejlkoden og aldrig på beskeden; beskeder er skrevet til mennesker og ændrer sig mellem udgivelser.
Tre kald er undtaget, fordi et menneske er læseren: referencesiden udskriver markdown, hjælp udskriver hjælpetekst, og version-flaget udskriver en ren versionsstreng. Intet andet lægger andet end ét JSON-dokument på stdout.
Ét flag indrykker JSON'en. Det ændrer whitespace og intet andet.
Exit-koder
Scripts forgrener på disse tal, så de er en del af grænsefladen.
| Kode | Betydning |
|---|---|
0 | Kaldet lykkedes. |
1 | Alt andet. |
2 | Argumenterne var forkerte. Intet blev sendt. |
3 | Nøglen manglede eller blev ikke accepteret. |
4 | Nøglen mangler verbet, eller målet ligger uden for dens rækkevidde. |
5 | Kaldet var velformet, men fejlede valideringen. |
6 | En kvote eller en rate limit blev ramt. |
7 | Tjenesten kunne ikke betjene kaldet. Kan prøves igen. |
8 | Kaldet nåede aldrig frem til tjenesten. |
9 | Det, der blev adresseret, findes ikke. |
Nøglen, og hvor den ligger
Send nøglen på standard input, eller lad den spørge, når der er en terminal. Begge dele holder hemmeligheden ude af proceslisten, hvor ps viser den til hver bruger på maskinen, og ude af din shell-historik. Flaget, der tager en nøgle som argument, findes, og det er det dårligste af de tre.
cat key.txt | pfmem init
pfmem init --origin https://api.example.comLæsningen fra standard input er begrænset til 8 KB og ti sekunder, så en harness, der efterlader røret åbent men tomt, får en brugsfejl med alternativerne nævnt frem for at hænge i det uendelige.
Nøglen læses først fra miljøet og derefter fra konfigurationsfilen, som oprettes læsbar kun for ejeren. Den udskrives aldrig, logges aldrig og gentages aldrig af diagnosekommandoen.
En nøgle læst fra den fil sendes kun til et https-origin eller til loopback. En gemt legitimation følger med hvert senere kald, uden at nogen tænker over det, så et origin, der navngiver en vært uden kryptering, afvises frem for at blive adlydt.
At overskrive origin for ét kald flytter aldrig det sted, klienten henter sin egen kode fra. Et flag pr. kald må ikke kunne udpege et installationsprogram.
Hvem denne maskine taler på vegne af
Enhver erindring tilhører et subjekt — en person, eller en agent, der noterer for sig selv. Opsætningen afgør det én gang og gemmer det, så senere kald ikke behøver nævne det. Uden det skrives subjektet ved hvert kald og kontrolleres mod ingenting, og en anden stavemåde af den samme person er et separat, tomt sted, der tager imod skrivninger og svarer på enhver senere læsning med ingenting.
Opsætningen spørger serveren først. En nøgle, der er udstedt til ét subjekt, bærer det allerede, og det svar gemmes uden at spørge, for en skrivning som en anden afvises alligevel. Ellers spørger den dig og foreslår en adresse, den finder i din git-opsætning, dernæst dit kontonavn på maskinen.
pfmem init
# Whose memories is this machine writing? [user/agent] (user)
# Which user id? ([email protected])
# or, with no terminal to ask at:
pfmem init --mode user --subject-id [email protected]Et id skal blot være stabilt og staves ens, uanset hvor du kalder fra. En e-mailadresse er et fint valg og er som regel den, der foreslås.
Uden en terminal spørges der om intet, for et spørgsmål, ingen er der til at besvare, venter for evigt. Angiv i stedet tilstand og id som flag; med ingen af delene gemmer opsætningen stadig nøglen, registrerer intet subjekt og siger det, og hvert kald navngiver så sit eget.
Derefter udfyldes både arten og subjektet for dig, når du udelader dem. Det, du selv angiver, vinder over det gemte, og ved en læsning findes et flag, der udvider igen til alle de subjekter, nøglen må se. Diagnosekommandoen viser, hvad der blev gemt.
# the kind and the subject are filled in from what init recorded
pfmem search --query "how do they prefer to travel"
# widen back out to every subject this key may see
pfmem search --memory-type user --all-subjects --query "billing"Hvad klienten ikke vil sende
Der findes ikke et flag for et arbejdsområde, en konto, et filter eller en embedding-version, og en test fastslår, at ingen kan tilføjes. Nøglen opløses til det hele på serveren. At sende et af dem er præcis den måde, en klient ville læse andres hukommelser på.
To afgrænsningsflag findes, og de indsnævrer kun inden for det arbejdsområde, nøglen allerede er opløst til. Udelader du dem, spænder kaldet over alt, den nøgle i forvejen kan se; ingen af dem kan udvide noget.
pfmem search --memory-type user --user-id u_42 --query "retry policy" --app-id support-bot
pfmem delete --created-before 1735689600000 --project-id billingHvad en nøgle får
CLI'et skriver altid til stdout med en nøgle, så reglerne her er synlige i det, det udskriver. Ikke-godkendt indhold kommer markeret, og det, der er tilbageholdt for nøglen, oplyses som et antal i stedet for et resultat.
{
"ok": true,
"request_id": "9130cb814f654e1ea042497d6362b08d",
"data": {
"hits": [
{
"record": {
"id": "a1b2c3",
"memory_type": "user",
"subject_id": "[email protected]",
"content": "[unverified] Prefers the night train to Berlin.",
"verification": "unverified",
"availability": "served"
},
"score": 0.0328,
"rank": 1
}
],
"method": "hybrid",
"embedding_version": "external_v1",
"took_ms": 41,
"withheld_count": 2
}
}Markeringen på ikke-godkendt indhold
[unverified]
Indhold, som ingen har godkendt, kommer tilbage med dette præfiks foran sin tekst. Præfikset lægges på svaret og gemmes aldrig, så den samme erindring, læst af et indlogget menneske, bærer intet præfiks.
Det tilbageholdte, som et antal
withheld_count
Når en søgning eller en liste udelader noget, fordi det er tilbageholdt for denne nøgle, står antallet i JSON'en, og pfmem skriver det også til stderr i menneskelig tilstand. Et resultat, der lydløst blev mindre, er en model, der læser en mindre sandhed, end der findes, og antallet er den eneste advarsel.
En fremgangsmåde udleverer den version, et menneske har godkendt, når der er en
pending_version
En nøgle får den nyeste version, et menneske har godkendt. Har en nøgle skrevet en nyere version, som ingen har godkendt endnu, svarer opslaget med den godkendte version og nævner den ventende i dette felt, så agenten følger en fremgangsmåde, nogen stod inde for. Er der aldrig godkendt nogen version, udleveres den nyeste med markøren i stedet: en fremgangsmåde, som kun en nøgle har skrevet, kan stadig bruges, og intet tilbageholdes, før der er en godkendt version at falde bagud for.
Hvor en godkendelse sker
Godkendelsen sker i dashboardet på siden under Gennemgang — Markeret til gennemgang. Intet, en nøgle sender, kan gøre en post betroet, og det er det, der holder "et menneske har godkendt dette" som et faktum.
Kommandoer
Referencekommandoen udskriver det hele i fuld længde — hvert flag, hver betingelse, hver svarform — genereret ud fra den samme specifikation, som argumentparseren bruger, så den kan ikke beskrive et flag, klienten ville afvise. Det er den side, du giver en model.
| Kommando | Hvad den gør |
|---|---|
add | Indlæser beskeder til udtrækning. Asynkron; returnerer et task-id. |
search | Rangerer hukommelser efter relevans for et spørgsmål i naturligt sprog. |
get | Viser et subjekts hukommelser, filtreret og pagineret. |
edit | Retter én hukommelse på stedet. |
delete | Sletter hukommelser efter id, efter session eller efter alder. |
flush | Kører en sessions ventende udtrækning nu. |
task · tasks · retry | Læser én baggrundsopgave, viser dem alle, eller kører en mislykket igen. |
procedure-* | Skriver, læser, versionerer, tager ud af brug, lister og søger i procedurer — den fremgangsmåde-hukommelse, et arbejdsområde holder. Den har sit eget afsnit nedenfor. |
init · doctor · logs · docs · update · version | Lokale. De sender ingen API-kald, men to af dem rører stadig netværket. |
skill install|status|update | Installerer, kontrollerer eller opdaterer den skill, en agent læser. |
Der findes ingen kommando, der gemmer rå tekst uden udtrækning, og ingen, der henter et referat frem. At læse før en rettelse er en visning, fordi en rettelse kræver hukommelsens id og dens version.
Globale flag
De gælder for hver kommando.
| Flag | Hvad det gør |
|---|---|
--pretty | Indrykker den JSON, der skrives til stdout. |
--verbose | Skriver diagnostik om kaldet i logfilen. |
--origin <url> | Overskriver API-origin for netop dette kald. |
--help, -h | Udskriver hjælp til kommandoen og afslutter. |
--version, -v | Udskriver versionen og afslutter. |
Logs
En JSONL-fil, læsbar kun for ejeren, der registrerer hvert kalds metode, sti, status, varighed og request-id samt fejl. Den roterer ved 1 MB og beholder én generation.
pfmem logs --lines 50Legitimationsoplysninger maskeres på vej ind: feltnavne som authorization, api_key og token; enhver nøglestreng hvor som helst i en besked, en URL eller en indlejret værdi; og enhver bearer-header.
Citér request-id'et fra en fejl. Tjenesten registrerer det samme id, og det er dét, der gør et problem sporbart fra din terminal til vores logs.
Opdateringer
Ved opstart kontrollerer klienten udgivelsesfeedet, cachet i seks timer. Findes der en nyere version, spørger den kun, hvis både standard input og standard error er en terminal; ellers skriver den én linje til standard error og fortsætter. En harness blokeres aldrig, og en utilgængelig opdateringstjeneste får aldrig et hukommelseskald til at fejle.
pfmem update
pfmem update --checkEn opdatering downloader, verificerer sha256 og udskifter bundtet atomisk. En kontrol rapporterer, hvad der er offentliggjort, og installerer intet.
Opdaterings- og skill-downloads kræver https, og installationsprogrammet fastholder protokollen på tværs af omdirigeringer. En checksum offentliggjort ved siden af et artefakt beviser kun, at bytes svarer til det, den samme server sendte; uden kryptering leverer en angriber på vejen begge dele, så det er transporten, der giver checksummen betydning. Et origin uden kryptering afvises, før der overhovedet sendes et kald.
Én miljøvariabel slår kontrollen helt fra.
PFMEM_NO_UPDATE_CHECK=1Procedurer
En procedure er en fremgangsmåde snarere end et faktum — hvordan I udgiver, hvordan I griber en alarm an, hvad trinnene rent faktisk er — og din assistent læser en, før den går i gang, i stedet for at genopfinde den. At skrive en giver et id tilbage, som alle senere kald bruger.
pfmem procedure-list --name-prefix release --limit 20
pfmem procedure-search --query "release freeze" --top-k 5
pfmem procedure-get --procedure-id pr_9f3c1a2e-5d47-4b8a-9c31-6e0d2f7b4a15
# that read came back at version 3, so append the next one conditionally
pfmem procedure-update --procedure-id pr_9f3c1a2e-5d47-4b8a-9c31-6e0d2f7b4a15 \
--content "Freeze at seven now." --expected-version 3 --reason "the freeze moved an hour"
pfmem procedure-versions --procedure-id pr_9f3c1a2e-5d47-4b8a-9c31-6e0d2f7b4a15
# the history lists versions without their text; read the one before the append
pfmem procedure-versions --procedure-id pr_9f3c1a2e-5d47-4b8a-9c31-6e0d2f7b4a15 --procedure-version 3
pfmem procedure-archive --procedure-id pr_9f3c1a2e-5d47-4b8a-9c31-6e0d2f7b4a15 --reason "replaced by a new runbook"
# retiring is one-way, so the way of working that replaces it is a new procedure
pfmem procedure-create --name nightly-release --visibility team \
--description "how we ship at night" \
--content "Freeze at seven, then {{shared:deploy-checks}}" \
--reason "replaces the retired nightly runbook"Søg, når du ved, at der nok findes en procedure, men ikke hvad den hed; list, når du vil se alt, denne nøgle kan nå. Begge svarer med sammendrag; kun søgningen tilføjer det afsnit, der matchede, med de matchende ord markeret, og selve teksten kommer fra læsningen.
En opdatering tilføjer en ny version og retter aldrig på stedet, så en gammel vejledning går aldrig tabt under en ny. Angiv den version, du læste, og en ændring, en anden nåede først, fejler tydeligt i stedet for at blive begravet. At tage en ud af brug fjerner den fra oversigt og søgning, mens dens tekst og alle versioner forbliver læsbare for enhver, der har id'et. Intet her sletter, og intet fortryder en udtagning: en procedure, der er taget ud af brug, får ingen flere versioner, så en afløser er en ny procedure.
En procedure er privat som udgangspunkt — dens ejende agent og enhver nøgle, der læser hele arbejdsområdet. At dele den med alle i arbejdsområdet er en beslutning, ikke en standard, og en opdatering kan flytte den begge veje. En nøgle uden en agent har ingen at holde en procedure privat for og må derfor dele dem, den skriver.
Kun det subjekt, der ejer en procedure, eller en nøgle uden noget subjekt overhovedet, kan tilføje til den eller tage den ud af brug. For alle andre svarer den som en, der ikke findes — så et afslag på en procedure, du kan se i oversigten, betyder, at den ikke er din at ændre, ikke at id'et er forkert. En master-nøgle er ikke sådan en nøgle her: den svarer for en konto og ikke for ét arbejdsområde, og denne klient sender aldrig et arbejdsområdes navn, så ethvert procedure-kald med den bliver afvist. Udsted en arbejdsområdenøgle, og giv klienten den.
De har intet med skill-kommandoerne nedenfor at gøre. En skill er én offentliggjort fil, der lærer din assistent at bruge denne klient; en procedure er indhold, dit arbejdsområde ejer og versionerer. At installere en skill gemmer ingen hukommelse, og at skrive en procedure installerer ingenting.
Skill'en
Klienten leveres med en skill: én fil, der lærer en agent, hvornår den skal bruge hukommelse, og hvordan den kaldes. Installér den, og din assistent holder op med at gætte sig til grænsefladen.
pfmem skill install
pfmem skill install --dir DIR
pfmem skill status
pfmem skill updateUden en angivet mappe vinder en projektkonfiguration fundet ved at gå opad fra den aktuelle mappe over konfigurationen på brugerniveau — at stå i et repository betyder dét repository. Findes ingen af delene, oplyser den begge steder, den kiggede, frem for at gætte en sti.