PageSourceSearch

https://www.passbolt.com/docs/assets/js/a3924889.41c0e935.js

js passbolt.com collected 2026-09-24 08:41:20 UTC 22,886 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkpassbolt_docs||=[]).push([[907],{58162(e,s,t){t.r(s),t.d(s,{assets:()=>h,contentTitle:()=>d,default:()=>x,frontMatter:()=>c,metadata:()=>r,toc:()=>u});const r=JSON.parse('{"id":"user/quickstart/go-cli","title":"Go CLI","description":"Quickstart with go-passbolt-cli, the command line client for passbolt","source":"@site/docs/user/quickstart/go-cli.mdx","sourceDirName":"user/quickstart","slug":"/user/quickstart/go-cli","permalink":"/docs/user/quickstart/go-cli","draft":false,"unlisted":false,"editUrl":"https://github.com/passbolt/passbolt-docs/blob/main/docs/user/quickstart/go-cli.mdx","tags":[],"version":"current","lastUpdatedAt":1787642754000,"frontMatter":{"title":"Go CLI","description":"Quickstart with go-passbolt-cli, the command line client for passbolt","sidebar_label":"Go CLI"},"sidebar":"userGuideSidebar","previous":{"title":"Troubleshooting","permalink":"/docs/user/quickstart/desktop/troubleshooting"},"next":{"title":"Quickstart","permalink":"/docs/user/quickstart/"}}');var n=t(74848),o=t(28453),i=t(4865),a=t(19365),l=t(25515);const c={title:"Go CLI",description:"Quickstart with go-passbolt-cli, the command line client for passbolt",sidebar_label:"Go CLI"},d=void 0,h={},u=[{value:"Install",id:"install",level:2},{value:"Configure the CLI",id:"configure-the-cli",level:2},{value:"Verify the server",id:"verify-the-server",level:2},{value:"First commands",id:"first-commands",level:2},{value:"Use passbolt in scripts",id:"use-passbolt-in-scripts",level:2},{value:"Inject secrets into a process",id:"inject-secrets-into-a-process",level:3},{value:"Parse output as JSON",id:"parse-output-as-json",level:3},{value:"Automation without a configuration file",id:"automation-without-a-configuration-file",level:3},{value:"Multi-factor authentication",id:"multi-factor-authentication",level:2},{value:"Going further",id:"going-further",level:2}];function p(e){const s={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)("div",{style:{display:"flex",gap:"1rem"},children:[(0,n.jsx)(l.A,{link:"https://www.passbolt.com/ce/docker",isUnderMainTitle:!0,children:"CE"}),(0,n.jsx)(l.A,{link:"https://www.passbolt.com/pricing/pro",isUnderMainTitle:!0,children:"Pro"}),(0,n.jsx)(l.A,{link:"https://www.passbolt.com/pricing/cloud",isUnderMainTitle:!0,children:"Cloud"})]}),"\n",(0,n.jsxs)(s.p,{children:["The ",(0,n.jsx)(s.a,{href:"https://github.com/passbolt/go-passbolt-cli",children:"go-passbolt-cli"})," tool lets you interact with your passbolt instance from a terminal: retrieve, create, update, share and delete resources, folders, users and groups, and inject secrets into scripts without ever writing them to disk."]}),"\n",(0,n.jsx)(s.admonition,{type:"note",children:(0,n.jsxs)(s.p,{children:["The Go CLI is developed in the open at ",(0,n.jsx)(s.a,{href:"https://github.com/passbolt/go-passbolt-cli",children:"github.com/passbolt/go-passbolt-cli"}),". To build your own integrations in Go, the underlying ",(0,n.jsx)(s.a,{href:"https://github.com/passbolt/go-passbolt",children:"go-passbolt module"})," might interest you."]})}),"\n",(0,n.jsx)(s.h2,{id:"install",children:"Install"}),"\n",(0,n.jsxs)(i.A,{children:[(0,n.jsx)(a.A,{value:"brew",label:"Homebrew",default:!0,children:(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-bash",children:"brew install passbolt/tap/go-passbolt-cli\n"})})}),(0,n.jsxs)(a.A,{value:"package",label:"Debian/RPM package",children:[(0,n.jsxs)(s.p,{children:["Download the deb or rpm package for your OS and architecture from the ",(0,n.jsx)(s.a,{href:"https://github.com/passbolt/go-passbolt-cli/releases/latest",children:"latest release"}),", then install it with your package manager, for example:"]}),(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-bash",children:"sudo dpkg -i go-passbolt-cli_*.deb\n"})})]}),(0,n.jsx)(a.A,{value:"archive",label:"Binary archive",children:(0,n.jsxs)(s.p,{children:["Download the archive for your OS and architecture from the ",(0,n.jsx)(s.a,{href:"https://github.com/passbolt/go-passbolt-cli/releases/latest",children:"latest release"}),". Tab completion and man pages need to be installed manually with this method."]})}),(0,n.jsxs)(a.A,{value:"go",label:"Go",children:[(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-bash",children:"go install github.com/passbolt/go-passbolt-cli@latest\n"})}
1),(0,n.jsxs)(s.p,{children:["This method names the binary ",(0,n.jsx)(s.code,{children:"go-passbolt-cli"})," instead of ",(0,n.jsx)(s.code,{children:"passbolt"}),", and does not install tab completion or man pages."]})]})]}),"\n",(0,n.jsxs)(s.p,{children:["All channels except ",(0,n.jsx)(s.code,{children:"go install"})," provide the command as ",(0,n.jsx)(s.code,{children:"passbolt"}),", which is what this guide uses. Community packages also exist, see ",(0,n.jsx)(s.a,{href:"https://repology.org/project/go:passbolt-cli/versions",children:"Repology"})," for what your distribution offers."]}),"\n",(0,n.jsx)(s.h2,{id:"configure-the-cli",children:"Configure the CLI"}),"\n",(0,n.jsx)(s.p,{children:"The CLI needs three pieces of information: your server address, your private key, and your passphrase."}),"\n",(0,n.jsx)(s.p,{children:"The recommended setup stores only the server address and the path to your private key file, and lets the CLI prompt you for the passphrase:"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-bash",children:"passbolt configure --serverAddress https://passbolt.example.org --userPrivateKeyFile /path/to/privatekey.asc\n"})}),"\n",(0,n.jsx)(s.p,{children:"You can export your private key from the browser extension profile. Keep the key file readable by you only:"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-bash",children:"chmod 600 /path/to/privatekey.asc\n"})}),"\n",(0,n.jsxs)(s.p,{children:["The configuration is written to a TOML file (",(0,n.jsx)(s.code,{children:"~/.config/go-passbolt-cli/go-passbolt-cli.toml"})," on Linux, ",(0,n.jsx)(s.code,{children:"~/Library/Application Support/go-passbolt-cli/"})," on macOS, ",(0,n.jsx)(s.code,{children:"%AppData%\\go-passbolt-cli\\"})," on Windows). The CLI creates the directory with ",(0,n.jsx)(s.code,{children:"0700"})," and keeps the file at ",(0,n.jsx)(s.code,{children:"0600"})," permissions."]}),"\n",(0,n.jsx)(s.admonition,{title:"Keep the passphrase out of the configuration",type:"warning",children:(0,n.jsxs)(s.p,{children:[(0,n.jsx)(s.code,{children:"passbolt configure"})," saves whatever you give it: passing ",(0,n.jsx)(s.code,{children:"--userPassword"})," stores your passphrase in clear text in the configuration file, and passing ",(0,n.jsx)(s.code,{children:"--userPrivateKey"})," inlines your armoured private key in it. Flags passed on the command line also end up in your shell history. Store only the server address and the key file path, and type the passphrase when prompted. Note that ",(0,n.jsx)(s.code,{children:"passbolt verify"})," also writes to this file (the server verification tokens, which are not sensitive), so the file exists and matters even when no passphrase is stored in it."]})}),"\n",(0,n.jsx)(s.admonition,{type:"note",children:(0,n.jsx)(s.p,{children:"Private keys without a passphrase are not supported, do not remove the passphrase from your key to skip the prompt."})}),"\n",(0,n.jsx)(s.h2,{id:"verify-the-server",children:"Verify the server"}),"\n",(0,n.jsx)(s.p,{children:"Run the server verification once:"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-bash",children:"passbolt verify\n"})}),"\n",(0,n.jsx)(s.p,{children:"The verification material is pinned in the configuration file, and every following command checks that the server key has not changed. Two consequences:"}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:["If your instance legitimately rotates its server key, run ",(0,n.jsx)(s.code,{children:"passbolt verify"})," again."]}),"\n",(0,n.jsx)(s.li,{children:"A setup that uses only environment variables, without a configuration file, has no server verification."}),"\n"]}),"\n",(0,n.jsx)(s.h2,{id:"first-commands",children:"First commands"}),"\n",(0,n.jsxs)(s.p,{children:["Commands follow the same structure: ",(0,n.jsx)(s.code,{children:"passbolt action entity"}),". The actions are ",(0,n.jsx)(s.code,{children:"create"}),", ",(0,n.jsx)(s.code,{children:"get"}),", ",(0,n.jsx)(s.code,{children:"list"}),", ",(0,n.jsx)(s.code,{children:"update"}),", ",(0,n.jsx)(s.code,{children:"delete"}),", ",(0,n.jsx)(s.code,{children:"move"}),", ",(0,n.jsx)(s.code,{children:"share"})," and ",(0,n.jsx)(s.code,{children:"export"}),", applied to ",(0,n.jsx)(s.code,{children:"resource"}),", ",(0,n.jsx)(s.code,{children:"folder"}),", ",(0,n.jsx)(s.code,{children:"user"})," or ",(0,n.jsx)(s.code,{children:"group"})," (",(0,n.jsx)(s.code,{children:"move"})," and ",(0,n.jsx)(s.code,{children:"share"})," apply to resources and folders, and ",(0,n.jsx)(s.code,{children:"export"})," writes a KeePass kdbx file). In passbolt, a password is called a resource."]}),"\n",(0,n.jsxs)(s.p,{children:["List your resources, choosing the displayed columns with ",(0,n.jsx)(s.code,{children:"--column"})," (repeat the flag for several columns):"]}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-bash",children:"passbolt list resource -c ID -c Name -c Username\n"})}),"\n",(0,n.jsxs)(s.p,{children:["There is no separate search command: ",(0,n.jsx)(s.code,{children:"search"})," and ",(0,n.jsx)(s.code,{children:"filter"}
1)," are aliases of ",(0,n.jsx)(s.code,{children:"list"}),", which accepts a ",(0,n.jsx)(s.code,{children:"--filter"})," expression."]}),"\n",(0,n.jsx)(s.p,{children:"Retrieve a resource, including its password, by id:"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-bash",children:"passbolt get resource --id <resource-id>\n"})}),"\n",(0,n.jsx)(s.p,{children:"Create a resource, which prints the id of the new resource:"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-bash",children:'passbolt create resource --name "Test Resource" --password "Strong Password"\n'})}),"\n",(0,n.jsx)(s.p,{children:"Share a resource with a user or a group:"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-bash",children:"passbolt share resource --id <resource-id> --type 7 --user <user-id>\n"})}),"\n",(0,n.jsxs)(s.p,{children:["Repeat ",(0,n.jsx)(s.code,{children:"--user"})," to share with several users, or use ",(0,n.jsx)(s.code,{children:"--group"}),". The permission types are:"]}),"\n",(0,n.jsxs)(s.table,{children:[(0,n.jsx)(s.thead,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.th,{children:"Code"}),(0,n.jsx)(s.th,{children:"Meaning"})]})}),(0,n.jsxs)(s.tbody,{children:[(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"1"})}),(0,n.jsx)(s.td,{children:"Read-only"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"7"})}),(0,n.jsx)(s.td,{children:"Can update"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"15"})}),(0,n.jsx)(s.td,{children:"Owner"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"-1"})}),(0,n.jsx)(s.td,{children:"Delete existing permission"})]})]})]}),"\n",(0,n.jsx)(s.h2,{id:"use-passbolt-in-scripts",children:"Use passbolt in scripts"}),"\n",(0,n.jsx)(s.h3,{id:"inject-secrets-into-a-process",children:"Inject secrets into a process"}),"\n",(0,n.jsxs)(s.p,{children:["The most secure way to hand a secret to a script or a tool is the ",(0,n.jsx)(s.code,{children:"exec"})," command: environment variables whose value starts with ",(0,n.jsx)(s.code,{children:"passbolt://"}),", followed by a resource id, are resolved to the resource's password in the child process environment only, without exposing the secret to your shell, your history, or stdout. The CLI also closes its passbolt session before starting the child command, so the session is not inherited."]}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-bash",children:"export GITHUB_TOKEN=passbolt://<resource-id>\npassbolt exec -- gh auth login\n"})}),"\n",(0,n.jsxs)(s.p,{children:["There is no field selector: a ",(0,n.jsx)(s.code,{children:"passbolt://"})," reference resolves to the password only. For other fields, such as the username, use ",(0,n.jsx)(s.code,{children:"get resource --json"}),"."]}),"\n",(0,n.jsx)(s.h3,{id:"parse-output-as-json",children:"Parse output as JSON"}),"\n",(0,n.jsxs)(s.p,{children:["The ",(0,n.jsx)(s.code,{children:"create"}),", ",(0,n.jsx)(s.code,{children:"get"})," and ",(0,n.jsx)(s.code,{children:"list"})," commands accept ",(0,n.jsx)(s.code,{children:"--json"})," (or ",(0,n.jsx)(s.code,{children:"-j"}),") for machine-readable output:"]}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-bash",children:"passbolt get resource --id <resource-id> --json | jq -r '.password'\n"})}),"\n",(0,n.jsx)(s.p,{children:"The JSON output does not cover error messages: detect failures by checking that the exit code is not 0."}),"\n",(0,n.jsx)(s.h3,{id:"automation-without-a-configuration-file",children:"Automation without a configuration file"}),"\n",(0,n.jsxs)(s.p,{children:["On a CI runner, do not run ",(0,n.jsx)(s.code,{children:"passbolt configure"}),": inject the settings through environment variables from your runner's secret store instead. The variable names are the configuration keys in upper case, without any prefix or separator: ",(0,n.jsx)(s.code,{children:"SERVERADDRESS"}),", ",(0,n.jsx)(s.code,{children:"USERPRIVATEKEY"}),", ",(0,n.jsx)(s.code,{children:"USERPASSWORD"}),", and the MFA and TLS keys (",(0,n.jsx)(s.code,{children:"MFAMODE"}),", ",(0,n.jsx)(s.code,{children:"MFATOTPTOKEN"}),", ",(0,n.jsx)(s.code,{children:"TLSSKIPVERIFY"}),", ...)."]}),"\n",(0,n.jsx)(s.admonition,{type:"caution",children:(0,n.jsxs)(s.p,{children:["There is no ",(0,n.jsx)(s.code,{children:"PASSBOLT_"})," prefix, ",(0,n.jsx)(s.code,{children:"PASSBOLT_SERVER_ADDRESS"})," does not work. And the key file shortcut is a flag only: in the environment, provide the private key itself through ",(0,n.jsx)(s.code,{children:"USERPRIVATEKEY"}),", not a file path."]})}),"\n",(0,n.jsxs)(s.p,{children:["Pair this setup with the ",(0,n.jsx)(s.code,{children:"exec"})," command to keep secrets out of the runner's logs, and mind that without a configuration file there is no server verification, as noted above."]}),"\n",(0,n.jsx)(s.h2,{id:"multi-factor-authentication",children:"Multi-factor authentication"}),"\n",(0,n.jsxs)(s.p,{children:["Only TOTP is supported, through the ",(0,n.jsx)(s.code,{children:"mfaMode"})," setting, which defaults to ",(0,n.jsx)(s.code,{children:"interactive-totp"}),":"]}),"\n",(0,n.jsxs)(s.table,{children:[(0,n.jsx)(s.thead,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.th,{children:"Mode"}),(0,n.jsx)(s.th,{children:"Behaviour"})]})}),(0,n.jsxs)(s.tbody,{children:[(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"none"})}),(0,n.jsx)(s.td,{children:"Errors if challenged for MFA."})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"interactive-totp"})}
1),(0,n.jsx)(s.td,{children:"Prompts you for the TOTP code. Recommended for interactive use."})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"noninteractive-totp"})}),(0,n.jsxs)(s.td,{children:["Generates TOTP codes automatically. Requires ",(0,n.jsx)(s.code,{children:"mfaTotpToken"})," set to your TOTP secret, tune with ",(0,n.jsx)(s.code,{children:"mfaDelay"}),", ",(0,n.jsx)(s.code,{children:"mfaRetrys"})," and ",(0,n.jsx)(s.code,{children:"mfaTotpOffset"}),"."]})]})]})]}),"\n",(0,n.jsx)(s.admonition,{type:"warning",children:(0,n.jsxs)(s.p,{children:["With ",(0,n.jsx)(s.code,{children:"noninteractive-totp"}),", the ",(0,n.jsx)(s.code,{children:"mfaTotpToken"})," value is your TOTP seed: saved through ",(0,n.jsx)(s.code,{children:"passbolt configure"}),", it is stored in clear text in the configuration file. Reserve this mode for automation where the seed lives in a secret store."]})}),"\n",(0,n.jsx)(s.h2,{id:"going-further",children:"Going further"}),"\n",(0,n.jsxs)(s.p,{children:["The usage of every subcommand is documented in the ",(0,n.jsx)(s.a,{href:"https://github.com/passbolt/go-passbolt-cli/wiki/passbolt",children:"go-passbolt-cli wiki"})," and in the man pages (",(0,n.jsx)(s.code,{children:"man passbolt"}),")."]})]})}function x(e={}){const{wrapper:s}={...(0,o.R)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},19365(e,s,t){t.d(s,{A:()=>l});t(96540);var r=t(18215),n=t(47751);const o="tabItem_Ymn6";var i=t(74848);function a({children:e,className:s,hidden:t}){return(0,i.jsx)("div",{role:"tabpanel",className:(0,r.A)(o,s),hidden:t,children:e})}function l({children:e,className:s,value:t}){const{selectedValue:r,lazy:o}=(0,n.uc)(),l=t===r;return!l&&o?null:(0,i.jsx)(a,{className:s,hidden:!l,children:e})}},4865(e,s,t){t.d(s,{A:()=>x});t(96540);var r=t(18215),n=t(17559),o=t(47751),i=t(23104),a=t(92303);const l="tabList__CuJ",c="tabItem_LNqP";var d=t(74848);function h({className:e}){const{selectedValue:s,selectValue:t,tabValues:n,block:a}=(0,o.uc)(),l=[],{blockElementScrollPositionUntilNextRender:h}=(0,i.a_)(),u=e=>{const r=e.currentTarget,o=l.indexOf(r),i=n[o].value;i!==s&&(h(r),t(i))},p=e=>{let s=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const t=l.indexOf(e.currentTarget)+1;s=l[t]??l[0];break}case"ArrowLeft":{const t=l.indexOf(e.currentTarget)-1;s=l[t]??l[l.length-1];break}}s?.focus()};return(0,d.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,r.A)("tabs",{"tabs--block":a},e),children:n.map(({value:e,label:t,attributes:n})=>(0,d.jsx)("li",{role:"tab",tabIndex:s===e?0:-1,"aria-selected":s===e,ref:e=>{l.push(e)},onKeyDown:p,onClick:u,...n,className:(0,r.A)("tabs__item",c,n?.className,{"tabs__item--active":s===e}),children:t??e},e))})}function u({children:e}){return(0,d.jsx)("div",{className:"margin-top--md",children:e})}function p({className:e,children:s}){return(0,d.jsxs)("div",{className:(0,r.A)(n.G.tabs.container,"tabs-container",l),children:[(0,d.jsx)(h,{className:e}),(0,d.jsx)(u,{children:s})]})}function x(e){const s=(0,a.A)(),t=(0,o.OC)(e);return(0,d.jsx)(o.O_,{value:t,children:(0,d.jsx)(p,{className:e.className,children:(0,o.vT)(e.children)})},String(s))}},47751(e,s,t){t.d(s,{OC:()=>x,O_:()=>f,uc:()=>m,vT:()=>d});var r=t(96540),n=t(56347),o=t(205),i=t(57485),a=t(70679),l=t(31682),c=t(74848);function d(e){return r.Children.toArray(e).filter(e=>"\n"!==e)}function h(e){const{values:s,children:t}=e;return(0,r.useMemo)(()=>{const e=s??function(e){return r.Children.toArray(e).flatMap(e=>{if(!e)return[];if((0,r.isValidElement)(e)&&function(e){const{props:s}=e;return!!s&&"object"==typeof s&&"value"in s}(e))return[e];const s="string"==typeof e.type?e.type:e.type.name;throw new Error(`Docusaurus error: Bad <Tabs> child <${s}>: all children of the <Tabs> component should be <TabItem>, and every <TabItem> should have a unique "value" prop.\nIf you do not want to pass on a "value" prop to the direct children of <Tabs>, you can also pass an explicit <Tabs values={...}> prop.`)}).map(({props:{value:e,label:s,attributes:t,default:r}})=>({value:e,label:s,attributes:t,default:r}))}(t);return function(e){const s=(0,l.XI)(e,(e,s)=>e.value===s.value);if(s.length>0)throw new Error(`Docusaurus error: Duplicate values "${s.map(e=>`'${e.value}'`).join(", ")}" found in <Tabs>. Every value needs to be unique.`)}(e),e},[s,t])}function u({value:e,tabValues:s}){return s.some(s=>s.value===e)}function p({queryString:e=!1,groupId:s}){const t=(0,n.W6)(),o=function({queryString:e=!1,groupId:s}){if("string"==typeof e)return e;if(!1===e)return null;if(!0===e&&!s)throw new Error('Docusaurus error: The <Tabs> component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return s??null}({queryString:e,groupId:s});return[(0,i.aZ)(o),(0,r.useCallback)(e=>{if(!o)return;const s=new URLSearchParams(t.location.search);s.set(o,e),t.replace({...t.location,search:s.toString()})},[o,t])]}function x(e){const{defaultValue:s,queryString:t=!1,groupId:n}=e,i=h(e),[l,c]=(0,r.useState)(()=>function({defaultValue:e,tabValues:s}){if(0===s.length)throw new Error("Docusaurus error: the <Tabs> component requires at least one <TabItem> children component");if(e){if(!u({value:e,tabValues:s}))throw new Error(`Docusaurus error: The <Tabs> has a defaultValue "${e}" but none of its children has the corresponding value. Available values are: ${s.map(e=>e.value).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return e}const t=s.find(e=>e.default)??s[0];if(!t)throw new Error("Unexpected error: 0 tabValues");return t.value}({defaultValue:s,tabValues:i})),[d,x]=p({queryString:t,groupId:n}),[j,m]=function({groupId:e}){const s=function(e){return e?`docusaurus.tab.${e}`:null}(e),[t,n]=(0,a.Dv)(s);return[t,(0,r.useCallback)(e=>{s&&n.set(e)},[s,n])]}({groupId:n}),f=(()=>{const e=d??j;return u({value:e,tabValues:i})?e:null})();(0,o.A)(()=>{f&&c(f)},[f]);return{selectedValue:l,selectValue:(0,r.useCallback)(e=>{if(!u({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);c(e),x(e),m(e)},[x,m,i]),tabValues:i,lazy:e.lazy??!1,block:e.block??!1}}const j=(0,r.createContext)(null);function m(){const e=r.useContext(j);if(!e)throw new Error("useTabsContext() must be used within a Tabs component");return e}function f(e){return(0,c.jsx)(j.Provider,{value:e.value,children:e.children})}},25515(e,s,t){t.d(s,{A:()=>h});var r=t(28774),n=t(5556),o=t.n(n);const i="chips_cpy_",a="link_WvDp",l="under-main-menu_SavF";var c=t(74848);const d=({children:e,link:s="",isUnderMainTitle:t=!1})=>{if(!e)return null;const n=s.length>0;return(0,c.jsx)("div",{className:`${t?l:""}`,children:n?(0,c.jsx)(r.A,{className:`${i} ${a}`,to:s,target:"_blank",children:e}):(0,c.jsx)("span",{className:i,children:e})})};d.propTypes={children:o().oneOfType([o().arrayOf(o().node),o().node]).isRequired,isUnderMainTitle:o().bool,link:o().string};const h=d},28453(e,s,t){t.d(s,{R:()=>i,x:()=>a});var r=t(96540);const n={},o=r.createContext(n);function i(e){const s=r.useContext(o);return r.useMemo(function(){return"function"==typeof e?e(s):{...s,...e}},[s,e])}function a(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:i(e.components),r.createElement(o.Provider,{value:s},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.