[{"data":1,"prerenderedAt":471},["ShallowReactive",2],{"navigation_docs":3,"-docs-getting-started-installation":59,"-docs-getting-started-installation-surround":466},[4,25,40],{"title":5,"path":6,"stem":7,"children":8,"page":24},"Getting Started","\u002Fdocs\u002Fgetting-started","docs\u002F1.getting-started",[9,14,19],{"title":10,"path":11,"stem":12,"icon":13},"Introduction","\u002Fdocs\u002Fgetting-started\u002Fintroduction","docs\u002F1.getting-started\u002F1.introduction","i-lucide-house",{"title":15,"path":16,"stem":17,"icon":18},"Installation","\u002Fdocs\u002Fgetting-started\u002Finstallation","docs\u002F1.getting-started\u002F2.installation","i-lucide-download",{"title":20,"path":21,"stem":22,"icon":23},"Using Porter","\u002Fdocs\u002Fgetting-started\u002Fusing-porter","docs\u002F1.getting-started\u002F3.using-porter","i-lucide-terminal",false,{"title":26,"path":27,"stem":28,"children":29,"page":24},"Architecture","\u002Fdocs\u002Farchitecture","docs\u002F2.architecture",[30,35],{"title":31,"path":32,"stem":33,"icon":34},"Overview","\u002Fdocs\u002Farchitecture\u002Foverview","docs\u002F2.architecture\u002F1.overview","i-lucide-layers",{"title":36,"path":37,"stem":38,"icon":39},"Receiver internals","\u002Fdocs\u002Farchitecture\u002Freceiver","docs\u002F2.architecture\u002F2.receiver","i-lucide-smartphone",{"title":41,"path":42,"stem":43,"children":44,"page":24},"Reference","\u002Fdocs\u002Freference","docs\u002F3.reference",[45,49,54],{"title":46,"path":47,"stem":48,"icon":23},"Commands","\u002Fdocs\u002Freference\u002Fcommands","docs\u002F3.reference\u002F1.commands",{"title":50,"path":51,"stem":52,"icon":53},"Wire format","\u002Fdocs\u002Freference\u002Fwire-format","docs\u002F3.reference\u002F2.wire-format","i-lucide-binary",{"title":55,"path":56,"stem":57,"icon":58},"Decisions","\u002Fdocs\u002Freference\u002Fdecisions","docs\u002F3.reference\u002F3.decisions","i-lucide-file-text",{"id":60,"title":15,"body":61,"description":459,"extension":460,"links":461,"meta":462,"navigation":463,"path":16,"seo":464,"stem":17,"__hash__":465},"docs\u002Fdocs\u002F1.getting-started\u002F2.installation.md",{"type":62,"value":63,"toc":450},"minimark",[64,77,82,87,122,126,144,147,151,160,212,219,244,263,267,275,354,357,386,397,401,404,443,446],[65,66,67,68,72,73,76],"p",{},"Porter is two programs. You need the ",[69,70,71],"strong",{},"sender"," on the machine holding the file\nand the ",[69,74,75],{},"receiver"," on the device with the camera.",[78,79,81],"h2",{"id":80},"the-sender","The sender",[83,84,86],"h3",{"id":85},"homebrew","Homebrew",[88,89,94],"pre",{"className":90,"code":91,"language":92,"meta":93,"style":93},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","brew install terrorsquad\u002Ftap\u002Fporter-sender\nporter-sender myfile.pdf\n","bash","",[95,96,97,113],"code",{"__ignoreMap":93},[98,99,102,106,110],"span",{"class":100,"line":101},"line",1,[98,103,105],{"class":104},"sBMFI","brew",[98,107,109],{"class":108},"sfazB"," install",[98,111,112],{"class":108}," terrorsquad\u002Ftap\u002Fporter-sender\n",[98,114,116,119],{"class":100,"line":115},2,[98,117,118],{"class":104},"porter-sender",[98,120,121],{"class":108}," myfile.pdf\n",[83,123,125],{"id":124},"pre-built-binary","Pre-built binary",[65,127,128,129,136,137,139,140,143],{},"Grab an archive for your platform from the\n",[130,131,135],"a",{"href":132,"rel":133},"https:\u002F\u002Fgithub.com\u002FTerrorSquad\u002Fporter\u002Freleases",[134],"nofollow","releases page"," — macOS and\nLinux, arm64 and x86_64. Extract it and put ",[95,138,118],{}," on your ",[95,141,142],{},"PATH",".",[65,145,146],{},"The binary is self-contained: copy it to the air-gapped machine and it runs\nwith nothing else installed. That is the point of the move to Rust — the\nsending machine needs no runtime, which matters most on the machine least\nlikely to have one.",[83,148,150],{"id":149},"from-source","From source",[65,152,153,154,159],{},"Requires a Rust toolchain (",[130,155,158],{"href":156,"rel":157},"https:\u002F\u002Frustup.rs",[134],"rustup","). No other dependencies.",[88,161,163],{"className":90,"code":162,"language":92,"meta":93,"style":93},"git clone https:\u002F\u002Fgithub.com\u002FTerrorSquad\u002Fporter\ncd porter\u002Frust-sender\ncargo build --release\n\n.\u002Ftarget\u002Frelease\u002Fporter-sender myfile.pdf\n",[95,164,165,176,185,197,204],{"__ignoreMap":93},[98,166,167,170,173],{"class":100,"line":101},[98,168,169],{"class":104},"git",[98,171,172],{"class":108}," clone",[98,174,175],{"class":108}," https:\u002F\u002Fgithub.com\u002FTerrorSquad\u002Fporter\n",[98,177,178,182],{"class":100,"line":115},[98,179,181],{"class":180},"s2Zo4","cd",[98,183,184],{"class":108}," porter\u002Frust-sender\n",[98,186,188,191,194],{"class":100,"line":187},3,[98,189,190],{"class":104},"cargo",[98,192,193],{"class":108}," build",[98,195,196],{"class":108}," --release\n",[98,198,200],{"class":100,"line":199},4,[98,201,203],{"emptyLinePlaceholder":202},true,"\n",[98,205,207,210],{"class":100,"line":206},5,[98,208,209],{"class":104},".\u002Ftarget\u002Frelease\u002Fporter-sender",[98,211,121],{"class":108},[65,213,214,215,218],{},"Or with ",[95,216,217],{},"mise"," from the repo root:",[88,220,222],{"className":90,"code":221,"language":92,"meta":93,"style":93},"mise run rust-install   # builds, then copies to ~\u002F.local\u002Fbin\u002Fporter-sender\nporter-sender myfile.pdf\n",[95,223,224,238],{"__ignoreMap":93},[98,225,226,228,231,234],{"class":100,"line":101},[98,227,217],{"class":104},[98,229,230],{"class":108}," run",[98,232,233],{"class":108}," rust-install",[98,235,237],{"class":236},"sHwdD","   # builds, then copies to ~\u002F.local\u002Fbin\u002Fporter-sender\n",[98,239,240,242],{"class":100,"line":115},[98,241,118],{"class":104},[98,243,121],{"class":108},[65,245,246,247,250,251,250,254,250,257,250,260,143],{},"Other tasks: ",[95,248,249],{},"rust-build",", ",[95,252,253],{},"rust-test",[95,255,256],{},"rust-check",[95,258,259],{},"rust-send",[95,261,262],{},"rust-serve",[78,264,266],{"id":265},"the-receiver","The receiver",[65,268,269,270,143],{},"Requires ",[130,271,274],{"href":272,"rel":273},"https:\u002F\u002Fflutter.dev\u002Fdocs\u002Fget-started\u002Finstall",[134],"Flutter",[276,277,278,318],"code-group",{},[88,279,282],{"className":90,"code":280,"filename":281,"language":92,"meta":93,"style":93},"cd flutter\nflutter pub get\nflutter build apk --release\n# → build\u002Fapp\u002Foutputs\u002Fflutter-apk\u002Fapp-release.apk\n","Android",[95,283,284,291,302,313],{"__ignoreMap":93},[98,285,286,288],{"class":100,"line":101},[98,287,181],{"class":180},[98,289,290],{"class":108}," flutter\n",[98,292,293,296,299],{"class":100,"line":115},[98,294,295],{"class":104},"flutter",[98,297,298],{"class":108}," pub",[98,300,301],{"class":108}," get\n",[98,303,304,306,308,311],{"class":100,"line":187},[98,305,295],{"class":104},[98,307,193],{"class":108},[98,309,310],{"class":108}," apk",[98,312,196],{"class":108},[98,314,315],{"class":100,"line":199},[98,316,317],{"class":236},"# → build\u002Fapp\u002Foutputs\u002Fflutter-apk\u002Fapp-release.apk\n",[88,319,322],{"className":90,"code":320,"filename":321,"language":92,"meta":93,"style":93},"cd flutter\nflutter pub get\nflutter build macos --release\n# → build\u002Fmacos\u002FBuild\u002FProducts\u002FRelease\u002FPorterRx.app\n","macOS",[95,323,324,330,338,349],{"__ignoreMap":93},[98,325,326,328],{"class":100,"line":101},[98,327,181],{"class":180},[98,329,290],{"class":108},[98,331,332,334,336],{"class":100,"line":115},[98,333,295],{"class":104},[98,335,298],{"class":108},[98,337,301],{"class":108},[98,339,340,342,344,347],{"class":100,"line":187},[98,341,295],{"class":104},[98,343,193],{"class":108},[98,345,346],{"class":108}," macos",[98,348,196],{"class":108},[98,350,351],{"class":100,"line":199},[98,352,353],{"class":236},"# → build\u002Fmacos\u002FBuild\u002FProducts\u002FRelease\u002FPorterRx.app\n",[65,355,356],{},"Or with mise from the repo root:",[88,358,360],{"className":90,"code":359,"language":92,"meta":93,"style":93},"mise run flutter-build     # release build, x86_64 half stripped\nmise run flutter-install   # copies PorterRx.app to \u002FApplications\n",[95,361,362,374],{"__ignoreMap":93},[98,363,364,366,368,371],{"class":100,"line":101},[98,365,217],{"class":104},[98,367,230],{"class":108},[98,369,370],{"class":108}," flutter-build",[98,372,373],{"class":236},"     # release build, x86_64 half stripped\n",[98,375,376,378,380,383],{"class":100,"line":115},[98,377,217],{"class":104},[98,379,230],{"class":108},[98,381,382],{"class":108}," flutter-install",[98,384,385],{"class":236},"   # copies PorterRx.app to \u002FApplications\n",[387,388,389,392,393,396],"note",{},[95,390,391],{},"flutter build macos"," produces a universal binary, so a release bundle carries\nan x86_64 half that never runs on Apple Silicon — 44.7 MB against 22 MB once\nstripped. The ",[95,394,395],{},"flutter-build"," mise task strips it.",[78,398,400],{"id":399},"verifying-the-install","Verifying the install",[65,402,403],{},"Send a small text file to yourself:",[88,405,407],{"className":90,"code":406,"language":92,"meta":93,"style":93},"echo \"hello from the other side\" > test.txt\nporter-sender test.txt --slideshow --speed=0.5\n",[95,408,409,430],{"__ignoreMap":93},[98,410,411,414,418,421,424,427],{"class":100,"line":101},[98,412,413],{"class":180},"echo",[98,415,417],{"class":416},"sMK4o"," \"",[98,419,420],{"class":108},"hello from the other side",[98,422,423],{"class":416},"\"",[98,425,426],{"class":416}," >",[98,428,429],{"class":108}," test.txt\n",[98,431,432,434,437,440],{"class":100,"line":115},[98,433,118],{"class":104},[98,435,436],{"class":108}," test.txt",[98,438,439],{"class":108}," --slideshow",[98,441,442],{"class":108}," --speed=0.5\n",[65,444,445],{},"Open the receiver, point it at the terminal, and the file should assemble,\nverify against its SHA-256, and save to Downloads.",[447,448,449],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}",{"title":93,"searchDepth":115,"depth":115,"links":451},[452,457,458],{"id":80,"depth":115,"text":81,"children":453},[454,455,456],{"id":85,"depth":187,"text":86},{"id":124,"depth":187,"text":125},{"id":149,"depth":187,"text":150},{"id":265,"depth":115,"text":266},{"id":399,"depth":115,"text":400},"Install the sender binary and the receiver app.","md",null,{},{"icon":18},{"title":15,"description":459},"IBJriUdAT0wLjOXrPQr31h4pnTP0_6Y4zj7KisL9v3Y",[467,469],{"title":10,"path":11,"stem":12,"description":468,"icon":13,"children":-1},"What Porter is, what it deliberately isn't, and when it's the right tool.",{"title":20,"path":21,"stem":22,"description":470,"icon":23,"children":-1},"Choosing an encoding, driving the sender, and the three ways to get a file back.",1786435085208]