[{"data":1,"prerenderedAt":1007},["ShallowReactive",2],{"docs-nav":3,"docs-\u002Fdocs\u002Fenvironment":78},[4,9,13,16,21,26,30,34,38,42,46,50,53,58,62,66,69,74],{"path":5,"title":6,"navTitle":6,"group":7,"order":8},"\u002Fdocs\u002Fcommands","Other commands","Guide",999,{"path":10,"title":11,"navTitle":12,"group":7,"order":8},"\u002Fdocs\u002Fcompaction","Context and compaction","Context & compaction",{"path":14,"title":15,"navTitle":15,"group":7,"order":8},"\u002Fdocs\u002Fconfiguration","Configuration",{"path":17,"title":18,"navTitle":18,"group":19,"order":20},"\u002Fdocs\u002Fenvironment","Environment variables","Reference",11,{"path":22,"title":23,"navTitle":23,"group":24,"order":25},"\u002Fdocs\u002Fflags","Flag reference","CLI",8,{"path":27,"title":28,"navTitle":28,"group":7,"order":29},"\u002Fdocs","Introduction",1,{"path":31,"title":32,"navTitle":32,"group":7,"order":33},"\u002Fdocs\u002Finstallation","Installation",2,{"path":35,"title":36,"navTitle":36,"group":19,"order":37},"\u002Fdocs\u002Fproviders","Providers",10,{"path":39,"title":40,"navTitle":40,"group":7,"order":41},"\u002Fdocs\u002Fquickstart","Quickstart",3,{"path":43,"title":44,"navTitle":45,"group":7,"order":8},"\u002Fdocs\u002Freleases","Releases and upgrading","Releases",{"path":47,"title":48,"navTitle":49,"group":7,"order":8},"\u002Fdocs\u002Frun","The run command","Running an audit",{"path":51,"title":52,"navTitle":52,"group":7,"order":8},"\u002Fdocs\u002Fsecurity","Security model",{"path":54,"title":55,"navTitle":56,"group":24,"order":57},"\u002Fdocs\u002Fsessions","Sessions and forking","Sessions",6,{"path":59,"title":60,"navTitle":61,"group":7,"order":8},"\u002Fdocs\u002Fskills-roles","Skills and roles","Skills & roles",{"path":63,"title":64,"navTitle":64,"group":19,"order":65},"\u002Fdocs\u002Ftools","Tool reference",12,{"path":67,"title":68,"navTitle":68,"group":7,"order":8},"\u002Fdocs\u002Ftroubleshooting","Troubleshooting",{"path":70,"title":71,"navTitle":72,"group":24,"order":73},"\u002Fdocs\u002Ftui","The interactive TUI","Interactive TUI",9,{"path":75,"title":76,"navTitle":77,"group":7,"order":8},"\u002Fdocs\u002Fweb-eval","Dashboard and evaluation","Dashboard & evaluation",{"id":79,"title":18,"body":80,"description":1000,"extension":1001,"group":19,"meta":1002,"navTitle":18,"navigation":1003,"order":20,"path":17,"seo":1004,"stem":1005,"__hash__":1006},"docs\u002Fdocs\u002Fenvironment.md",{"type":81,"value":82,"toc":986},"minimark",[83,87,91,114,119,124,131,172,180,235,243,286,296,300,378,387,391,396,437,440,448,459,463,524,541,547,553,560,564,597,604,608,617,674,687,690,697,716,720,730,750,788,869,884,888,894,941,944,951,955,982],[84,85,18],"h1",{"id":86},"environment-variables",[88,89,90],"p",{},"Three separate sets of variables matter, and conflating them is a security bug:",[92,93,94,102,108],"ol",{},[95,96,97,101],"li",{},[98,99,100],"strong",{},"What locac reads:"," your keys, your home directory, your shell.",[95,103,104,107],{},[98,105,106],{},"What locac sets"," for the commands it spawns: the run's identity, and nothing more.",[95,109,110,113],{},[98,111,112],{},"What a spawned command inherits:"," a short allow-list, because everything locac spawns is\nrunning target code.",[115,116,118],"h2",{"id":117},"what-locac-reads","What locac reads",[120,121,123],"h3",{"id":122},"provider-credentials","Provider credentials",[88,125,126,127,130],{},"Every built-in provider reads one key variable and one base-URL override. The full table is on the\n",[128,129,36],"a",{"href":35}," page; the key variables are:",[88,132,133,137,138,137,141,137,144,147,148,137,151,137,154,137,157,137,160,147,163,137,166,137,169],{},[134,135,136],"code",{},"ANTHROPIC_API_KEY"," · ",[134,139,140],{},"OPENAI_API_KEY",[134,142,143],{},"GROQ_API_KEY",[134,145,146],{},"OPENROUTER_API_KEY"," ·\n",[134,149,150],{},"TOGETHER_API_KEY",[134,152,153],{},"XAI_API_KEY",[134,155,156],{},"DEEPSEEK_API_KEY",[134,158,159],{},"MOONSHOT_API_KEY",[134,161,162],{},"ZAI_API_KEY",[134,164,165],{},"VLLM_API_KEY",[134,167,168],{},"LMSTUDIO_API_KEY",[134,170,171],{},"OLLAMA_API_KEY",[88,173,174,176,177,179],{},[134,175,156],{}," and ",[134,178,159],{}," each serve two providers: that vendor's\nAnthropic-shaped and OpenAI-shaped endpoints both read the same variable.",[88,181,182,183,186,187,186,190,193,194,186,197,186,200,186,203,186,206,193,209,186,212,186,215,193,218,186,221,186,224,186,227,230,231,234],{},"The matching base-URL overrides are ",[134,184,185],{},"ANTHROPIC_BASE_URL",", ",[134,188,189],{},"OPENAI_BASE_URL",[134,191,192],{},"GROQ_BASE_URL",",\n",[134,195,196],{},"OPENROUTER_BASE_URL",[134,198,199],{},"TOGETHER_BASE_URL",[134,201,202],{},"XAI_BASE_URL",[134,204,205],{},"ZAI_BASE_URL",[134,207,208],{},"DEEPSEEK_BASE_URL",[134,210,211],{},"DEEPSEEK_OPENAI_BASE_URL",[134,213,214],{},"MOONSHOT_BASE_URL",[134,216,217],{},"MOONSHOT_OPENAI_BASE_URL",[134,219,220],{},"MOONSHOT_OPENAI_CN_BASE_URL",[134,222,223],{},"VLLM_BASE_URL",[134,225,226],{},"LMSTUDIO_BASE_URL",[134,228,229],{},"OLLAMA_OPENAI_BASE_URL",", and\n",[134,232,233],{},"OLLAMA_HOST"," for the native Ollama protocol.",[88,236,237,238,242],{},"A key can also be referenced ",[239,240,241],"em",{},"from"," the config file rather than inlined, which keeps the secret in\nyour shell profile and out of a file you might paste:",[244,245,250],"pre",{"className":246,"code":247,"language":248,"meta":249,"style":249},"language-json shiki shiki-themes vitesse-dark","{ \"apiKey\": \"$ANTHROPIC_API_KEY\" }\n","json","",[134,251,252],{"__ignoreMap":249},[253,254,256,260,264,268,271,274,277,281,283],"span",{"class":255,"line":29},"line",[253,257,259],{"class":258},"s_pn2","{",[253,261,263],{"class":262},"s6USN"," \"",[253,265,267],{"class":266},"sm68I","apiKey",[253,269,270],{"class":262},"\"",[253,272,273],{"class":258},":",[253,275,263],{"class":276},"sNJcY",[253,278,280],{"class":279},"s7rlk","$ANTHROPIC_API_KEY",[253,282,270],{"class":276},[253,284,285],{"class":258}," }\n",[88,287,288,289,176,292,295],{},"Both ",[134,290,291],{},"\"$VAR\"",[134,293,294],{},"\"${VAR}\""," are expanded once, at run time. An unset variable resolves to nothing\nrather than to an empty string, so the run fails loudly instead of sending a blank credential.",[120,297,299],{"id":298},"locacs-own","locac's own",[301,302,303,319],"table",{},[304,305,306],"thead",{},[307,308,309,313,316],"tr",{},[310,311,312],"th",{},"Variable",[310,314,315],{},"Default",[310,317,318],{},"What it does",[320,321,322,342,365],"tbody",{},[307,323,324,330,335],{},[325,326,327],"td",{},[134,328,329],{},"LOCAC_HOME",[325,331,332],{},[134,333,334],{},"~\u002F.locac",[325,336,337,338,341],{},"Where config, skills, roles, keybindings, session databases and extracted runtime assets live. ",[98,339,340],{},"Never"," the target repository",[307,343,344,349,352],{},[325,345,346],{},[134,347,348],{},"LOCAC_SHELL",[325,350,351],{},"auto-discovered",[325,353,354,355,186,358,361,362],{},"Path to a bash-compatible shell for ",[134,356,357],{},"bash",[134,359,360],{},"execute"," and the sandbox. Same as ",[134,363,364],{},"--shell-path",[307,366,367,372,375],{},[325,368,369],{},[134,370,371],{},"LOCAC_PASSTHROUGH_ENV",[325,373,374],{},"unset",[325,376,377],{},"Comma-separated extra variable names to admit into spawned commands. See the allow-list below",[88,379,380,382,383,386],{},[134,381,329],{}," is the anchor of the whole trust model. Everything locac treats as ",[239,384,385],{},"operator","\ninput, from configuration and prompt overrides to skills, roles and key bindings, is read from there and\nnowhere else. The repository under audit is attacker-authored, so a config read from it would let\nthe target choose your provider, your base URL and your API key.",[120,388,390],{"id":389},"shell-resolution","Shell resolution",[88,392,393,395],{},[134,394,348],{}," sits second in a five-step chain:",[92,397,398,407,411,420,423],{},[95,399,400,402,403,406],{},[134,401,364],{},", or ",[134,404,405],{},"shellPath"," from the config (CLI and per-project overrides already merged)",[95,408,409],{},[134,410,348],{},[95,412,413,415,416,419],{},[134,414,357],{}," on ",[134,417,418],{},"PATH",", unless it is the WSL launcher, which is skipped in favour of a native bash",[95,421,422],{},"Common Windows install locations",[95,424,425,426,429,430,433,434],{},"No bash: fall back to ",[134,427,428],{},"sh",", else PowerShell (",[134,431,432],{},"-NoProfile -NonInteractive","), else ",[134,435,436],{},"cmd \u002Fc",[88,438,439],{},"An explicit-but-missing path does not hard-fail. It warns once and falls through to auto-discovery,\nso a stale config entry can never brick a run:",[244,441,446],{"className":442,"code":444,"language":445,"meta":249},[443],"language-text","locac: shellPath \"C:\\Program Files\\Git\\bin\\bash.exe\" not found; falling back to auto-discovery\n","text",[134,447,444],{"__ignoreMap":249},[88,449,450,451,454,455,458],{},"The PowerShell fallback is deliberately not given ",[134,452,453],{},"-ExecutionPolicy Bypass",": the target repo is\nattacker-authored, and its ",[134,456,457],{},".ps1"," files should stay exactly as hard to run as your host says they\nare.",[120,460,462],{"id":461},"editor","Editor",[301,464,465,477],{},[304,466,467],{},[307,468,469,471,474],{},[310,470,312],{},[310,472,473],{},"Read by",[310,475,476],{},"Order",[320,478,479,503],{},[307,480,481,489,494],{},[325,482,483,186,486],{},[134,484,485],{},"EDITOR",[134,487,488],{},"VISUAL",[325,490,491],{},[134,492,493],{},"locac skills edit \u003Cname>",[325,495,496,499,500],{},[134,497,498],{},"$EDITOR",", then ",[134,501,502],{},"$VISUAL",[307,504,505,511,518],{},[325,506,507,186,509],{},[134,508,488],{},[134,510,485],{},[325,512,513,514,517],{},"The TUI's ",[134,515,516],{},"Ctrl+G"," draft handoff",[325,519,520,499,522],{},[134,521,502],{},[134,523,498],{},[88,525,526,527,529,530,532,533,536,537,540],{},"The two orders differ on purpose. ",[134,528,516],{}," hands your whole draft to an editor and takes back what\nyou save, which wants the POSIX definition of ",[134,531,488],{},", the ",[239,534,535],{},"full-screen"," editor. ",[134,538,539],{},"skills edit","\njust opens a file.",[88,542,543,544,546],{},"With neither set, ",[134,545,539],{}," prints the path instead of failing:",[244,548,551],{"className":549,"code":550,"language":445,"meta":249},[443],"\u002Fhome\u002Fyou\u002F.locac\u002Fskills\u002Fmy-skill\u002FSKILL.md\n(set $EDITOR to open it automatically)\n",[134,552,550],{"__ignoreMap":249},[88,554,555,556,559],{},"A value with arguments works: ",[134,557,558],{},"EDITOR=\"code -w\""," reaches the spawn as two words.",[120,561,563],{"id":562},"terminal","Terminal",[301,565,566,575],{},[304,567,568],{},[307,569,570,572],{},[310,571,312],{},[310,573,574],{},"Effect",[320,576,577,587],{},[307,578,579,584],{},[325,580,581],{},[134,582,583],{},"NO_COLOR",[325,585,586],{},"Set to anything, and all ANSI colour is suppressed",[307,588,589,594],{},[325,590,591],{},[134,592,593],{},"TERM=dumb",[325,595,596],{},"Same",[88,598,599,600,603],{},"Colour is emitted only when stdout is a real TTY ",[239,601,602],{},"and"," neither of those applies, so piping to a file\nor a pager already gives you plain text without setting anything.",[115,605,607],{"id":606},"what-locac-sets-for-spawned-commands","What locac sets for spawned commands",[88,609,610,611,613,614,616],{},"Every command locac spawns, whether the ",[134,612,357],{}," tool, ",[134,615,360],{},", a sandbox-wrapped argv or a target\nbuild, inherits these:",[301,618,619,628],{},[304,620,621],{},[307,622,623,625],{},[310,624,312],{},[310,626,627],{},"Value",[320,629,630,640,650,660],{},[307,631,632,637],{},[325,633,634],{},[134,635,636],{},"LOCAC_SESSION_ID",[325,638,639],{},"The current session id. Absent when there is no session",[307,641,642,647],{},[325,643,644],{},[134,645,646],{},"LOCAC_MODEL",[325,648,649],{},"The active model id",[307,651,652,657],{},[325,653,654],{},[134,655,656],{},"LOCAC_PROVIDER",[325,658,659],{},"The active provider id",[307,661,662,667],{},[325,663,664],{},[134,665,666],{},"LOCAC_EFFORT",[325,668,669,670,673],{},"The reasoning level actually going out on the wire. ",[98,671,672],{},"Absent",", not empty, when the endpoint carries none",[88,675,676,678,679,682,683,686],{},[134,677,666],{}," is omitted rather than set to ",[134,680,681],{},"\"\""," because a script asking ",[134,684,685],{},"[ -n \"$LOCAC_EFFORT\" ]","\nshould be able to tell \"the operator chose no effort\" from \"this endpoint has no effort knob\".",[88,688,689],{},"These let a PoC stamp its output with the run it belongs to, and let a build detect that it is\nrunning under the harness, without a side-channel file.",[88,691,692,693,696],{},"What is deliberately ",[98,694,695],{},"not"," there is the design:",[698,699,700,710],"ul",{},[95,701,702,705,706,709],{},[98,703,704],{},"Never the API key."," One ",[134,707,708],{},"env"," in a Makefile or a postinstall script would exfiltrate it.",[95,711,712,715],{},[98,713,714],{},"Never the session database path."," The store lives outside the sandbox root, so naming it to\nattacker-authored code buys the attacker a target and locac nothing.",[115,717,719],{"id":718},"what-a-spawned-command-inherits","What a spawned command inherits",[88,721,722,723,726,727,729],{},"Handing target code ",[134,724,725],{},"{...process.env}"," hands it your provider keys, your cloud and CI tokens, and\n",[134,728,329],{},", which points at the file holding the key. So locac allow-lists its own environment\ndown to what a process needs in order to start, and drops everything else.",[88,731,732,733,736,737,186,740,186,743,746,747,749],{},"Matching is ",[98,734,735],{},"case-insensitive",", because Windows spells these ",[134,738,739],{},"Path",[134,741,742],{},"SystemRoot",[134,744,745],{},"ComSpec",", and\na case-sensitive list would strip ",[134,748,418],{}," itself there.",[88,751,752,755,756,137,758,137,761,137,764,137,767,137,770,137,773,137,776,147,779,137,782,137,785],{},[98,753,754],{},"POSIX:"," ",[134,757,418],{},[134,759,760],{},"HOME",[134,762,763],{},"SHELL",[134,765,766],{},"TMPDIR",[134,768,769],{},"USER",[134,771,772],{},"LOGNAME",[134,774,775],{},"LANG",[134,777,778],{},"LC_ALL",[134,780,781],{},"LC_CTYPE",[134,783,784],{},"TERM",[134,786,787],{},"TZ",[88,789,790,793,794,137,797,147,800,137,803,137,806,137,809,137,812,137,815,137,818,137,821,147,824,137,827,137,830,137,833,137,836,137,839,147,842,137,845,137,848,137,851,147,854,137,857,137,860,137,863,137,866],{},[98,791,792],{},"Windows"," (a process will not even start without the first three): ",[134,795,796],{},"SYSTEMROOT",[134,798,799],{},"SYSTEMDRIVE",[134,801,802],{},"WINDIR",[134,804,805],{},"COMSPEC",[134,807,808],{},"PATHEXT",[134,810,811],{},"TEMP",[134,813,814],{},"TMP",[134,816,817],{},"USERPROFILE",[134,819,820],{},"HOMEDRIVE",[134,822,823],{},"HOMEPATH",[134,825,826],{},"APPDATA",[134,828,829],{},"LOCALAPPDATA",[134,831,832],{},"PROGRAMDATA",[134,834,835],{},"PROGRAMFILES",[134,837,838],{},"PROGRAMFILES(X86)",[134,840,841],{},"PROGRAMW6432",[134,843,844],{},"COMMONPROGRAMFILES",[134,846,847],{},"COMMONPROGRAMFILES(X86)",[134,849,850],{},"COMMONPROGRAMW6432",[134,852,853],{},"ALLUSERSPROFILE",[134,855,856],{},"PUBLIC",[134,858,859],{},"DRIVERDATA",[134,861,862],{},"NUMBER_OF_PROCESSORS",[134,864,865],{},"PROCESSOR_ARCHITECTURE",[134,867,868],{},"OS",[88,870,871,872,874,875,874,878,874,881,883],{},"Note what is absent: no ",[134,873,136],{},", no ",[134,876,877],{},"GITHUB_TOKEN",[134,879,880],{},"AWS_*",[134,882,329],{},".",[120,885,887],{"id":886},"re-admitting-a-variable","Re-admitting a variable",[88,889,890,891,893],{},"Real builds need real variables. ",[134,892,371],{}," is the operator's escape hatch, never the\ntarget's, because the target cannot set it:",[244,895,898],{"className":896,"code":897,"language":357,"meta":249,"style":249},"language-bash shiki shiki-themes vitesse-dark","export LOCAC_PASSTHROUGH_ENV=\"JAVA_HOME,MAVEN_OPTS,CARGO_HOME\"\nlocac run \"build the project and audit the deserialization path\" --auto\n",[134,899,900,921],{"__ignoreMap":249},[253,901,902,906,910,913,915,918],{"class":255,"line":29},[253,903,905],{"class":904},"s_wWq","export",[253,907,909],{"class":908},"st-jp"," LOCAC_PASSTHROUGH_ENV",[253,911,912],{"class":258},"=",[253,914,270],{"class":276},[253,916,917],{"class":279},"JAVA_HOME,MAVEN_OPTS,CARGO_HOME",[253,919,920],{"class":276},"\"\n",[253,922,923,927,930,932,935,937],{"class":255,"line":33},[253,924,926],{"class":925},"sCK9x","locac",[253,928,929],{"class":279}," run",[253,931,263],{"class":276},[253,933,934],{"class":279},"build the project and audit the deserialization path",[253,936,270],{"class":276},[253,938,940],{"class":939},"sXjYR"," --auto\n",[88,942,943],{},"Names are comma-separated, trimmed and matched case-insensitively.",[88,945,946,947,950],{},"Add only what the build actually needs. Every name you add is a name the target's ",[134,948,949],{},"Makefile"," can\nread.",[115,952,954],{"id":953},"next","Next",[88,956,957,959,960,962,963,965,966,186,968,176,971,974,975,978,979,981],{},[128,958,15],{"href":14}," covers the config file these variables interact with, and the\n",[128,961,23],{"href":22}," lists their command-line equivalents: ",[134,964,364],{}," for\n",[134,967,348],{},[134,969,970],{},"--api-key",[134,972,973],{},"--base-url"," for the provider variables, and ",[134,976,977],{},"--config"," to point at a\nconfig file outside ",[134,980,329],{}," entirely.",[983,984,985],"style",{},"html pre.shiki code .s_pn2, html code.shiki .s_pn2{--shiki-default:#666666}html pre.shiki code .s6USN, html code.shiki .s6USN{--shiki-default:#B8A96577}html pre.shiki code .sm68I, html code.shiki .sm68I{--shiki-default:#B8A965}html pre.shiki code .sNJcY, html code.shiki .sNJcY{--shiki-default:#C98A7D77}html pre.shiki code .s7rlk, html code.shiki .s7rlk{--shiki-default:#C98A7D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s_wWq, html code.shiki .s_wWq{--shiki-default:#CB7676}html pre.shiki code .st-jp, html code.shiki .st-jp{--shiki-default:#BD976A}html pre.shiki code .sCK9x, html code.shiki .sCK9x{--shiki-default:#80A665}html pre.shiki code .sXjYR, html code.shiki .sXjYR{--shiki-default:#C99076}",{"title":249,"searchDepth":41,"depth":41,"links":987},[988,995,996,999],{"id":117,"depth":33,"text":118,"children":989},[990,991,992,993,994],{"id":122,"depth":41,"text":123},{"id":298,"depth":41,"text":299},{"id":389,"depth":41,"text":390},{"id":461,"depth":41,"text":462},{"id":562,"depth":41,"text":563},{"id":606,"depth":33,"text":607},{"id":718,"depth":33,"text":719,"children":997},[998],{"id":886,"depth":41,"text":887},{"id":953,"depth":33,"text":954},"Every variable locac reads, every variable it sets for the commands it spawns, and the allow-list that decides what a spawned target process is allowed to inherit.","md",{},true,{"title":18,"description":1000},"docs\u002Fenvironment","yqjaaIc2GVZ3tv9eYwJ7Y4tvy5NePFsNEyquuScdnO4",1786794387820]