[{"data":1,"prerenderedAt":425},["ShallowReactive",2],{"navigation_docs":3,"-docs-getting-started-installation":59,"-docs-getting-started-installation-surround":420},[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":413,"extension":414,"links":415,"meta":416,"navigation":417,"path":16,"seo":418,"stem":17,"__hash__":419},"docs\u002Fdocs\u002F1.getting-started\u002F2.installation.md",{"type":62,"value":63,"toc":406},"minimark",[64,77,82,93,157,164,169,172,199,219,223,231,310,313,342,353,357,360,399,402],[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",[65,83,84,85,92],{},"Requires a Rust toolchain (",[86,87,91],"a",{"href":88,"rel":89},"https:\u002F\u002Frustup.rs",[90],"nofollow","rustup","). No other dependencies.",[94,95,100],"pre",{"className":96,"code":97,"language":98,"meta":99,"style":99},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","git clone https:\u002F\u002Fgithub.com\u002FTerrorSquad\u002Fporter\ncd porter\u002Frust-sender\ncargo build --release\n\n.\u002Ftarget\u002Frelease\u002Fporter-sender myfile.pdf\n","bash","",[101,102,103,119,129,141,148],"code",{"__ignoreMap":99},[104,105,108,112,116],"span",{"class":106,"line":107},"line",1,[104,109,111],{"class":110},"sBMFI","git",[104,113,115],{"class":114},"sfazB"," clone",[104,117,118],{"class":114}," https:\u002F\u002Fgithub.com\u002FTerrorSquad\u002Fporter\n",[104,120,122,126],{"class":106,"line":121},2,[104,123,125],{"class":124},"s2Zo4","cd",[104,127,128],{"class":114}," porter\u002Frust-sender\n",[104,130,132,135,138],{"class":106,"line":131},3,[104,133,134],{"class":110},"cargo",[104,136,137],{"class":114}," build",[104,139,140],{"class":114}," --release\n",[104,142,144],{"class":106,"line":143},4,[104,145,147],{"emptyLinePlaceholder":146},true,"\n",[104,149,151,154],{"class":106,"line":150},5,[104,152,153],{"class":110},".\u002Ftarget\u002Frelease\u002Fporter-sender",[104,155,156],{"class":114}," myfile.pdf\n",[65,158,159,160,163],{},"The result is a self-contained binary. Copy ",[101,161,162],{},"target\u002Frelease\u002Fporter-sender"," to\nthe air-gapped machine and it runs with nothing else installed.",[165,166,168],"h3",{"id":167},"with-mise","With mise",[65,170,171],{},"From the repo root:",[94,173,175],{"className":96,"code":174,"language":98,"meta":99,"style":99},"mise run rust-install   # builds, then copies to ~\u002F.local\u002Fbin\u002Fporter-sender\nporter-sender myfile.pdf\n",[101,176,177,192],{"__ignoreMap":99},[104,178,179,182,185,188],{"class":106,"line":107},[104,180,181],{"class":110},"mise",[104,183,184],{"class":114}," run",[104,186,187],{"class":114}," rust-install",[104,189,191],{"class":190},"sHwdD","   # builds, then copies to ~\u002F.local\u002Fbin\u002Fporter-sender\n",[104,193,194,197],{"class":106,"line":121},[104,195,196],{"class":110},"porter-sender",[104,198,156],{"class":114},[65,200,201,202,205,206,205,209,205,212,205,215,218],{},"Other tasks: ",[101,203,204],{},"rust-build",", ",[101,207,208],{},"rust-test",[101,210,211],{},"rust-check",[101,213,214],{},"rust-send",[101,216,217],{},"rust-serve",".",[78,220,222],{"id":221},"the-receiver","The receiver",[65,224,225,226,218],{},"Requires ",[86,227,230],{"href":228,"rel":229},"https:\u002F\u002Fflutter.dev\u002Fdocs\u002Fget-started\u002Finstall",[90],"Flutter",[232,233,234,274],"code-group",{},[94,235,238],{"className":96,"code":236,"filename":237,"language":98,"meta":99,"style":99},"cd flutter\nflutter pub get\nflutter build apk --release\n# → build\u002Fapp\u002Foutputs\u002Fflutter-apk\u002Fapp-release.apk\n","Android",[101,239,240,247,258,269],{"__ignoreMap":99},[104,241,242,244],{"class":106,"line":107},[104,243,125],{"class":124},[104,245,246],{"class":114}," flutter\n",[104,248,249,252,255],{"class":106,"line":121},[104,250,251],{"class":110},"flutter",[104,253,254],{"class":114}," pub",[104,256,257],{"class":114}," get\n",[104,259,260,262,264,267],{"class":106,"line":131},[104,261,251],{"class":110},[104,263,137],{"class":114},[104,265,266],{"class":114}," apk",[104,268,140],{"class":114},[104,270,271],{"class":106,"line":143},[104,272,273],{"class":190},"# → build\u002Fapp\u002Foutputs\u002Fflutter-apk\u002Fapp-release.apk\n",[94,275,278],{"className":96,"code":276,"filename":277,"language":98,"meta":99,"style":99},"cd flutter\nflutter pub get\nflutter build macos --release\n# → build\u002Fmacos\u002FBuild\u002FProducts\u002FRelease\u002FPorterRx.app\n","macOS",[101,279,280,286,294,305],{"__ignoreMap":99},[104,281,282,284],{"class":106,"line":107},[104,283,125],{"class":124},[104,285,246],{"class":114},[104,287,288,290,292],{"class":106,"line":121},[104,289,251],{"class":110},[104,291,254],{"class":114},[104,293,257],{"class":114},[104,295,296,298,300,303],{"class":106,"line":131},[104,297,251],{"class":110},[104,299,137],{"class":114},[104,301,302],{"class":114}," macos",[104,304,140],{"class":114},[104,306,307],{"class":106,"line":143},[104,308,309],{"class":190},"# → build\u002Fmacos\u002FBuild\u002FProducts\u002FRelease\u002FPorterRx.app\n",[65,311,312],{},"Or with mise from the repo root:",[94,314,316],{"className":96,"code":315,"language":98,"meta":99,"style":99},"mise run flutter-build     # release build, x86_64 half stripped\nmise run flutter-install   # copies PorterRx.app to \u002FApplications\n",[101,317,318,330],{"__ignoreMap":99},[104,319,320,322,324,327],{"class":106,"line":107},[104,321,181],{"class":110},[104,323,184],{"class":114},[104,325,326],{"class":114}," flutter-build",[104,328,329],{"class":190},"     # release build, x86_64 half stripped\n",[104,331,332,334,336,339],{"class":106,"line":121},[104,333,181],{"class":110},[104,335,184],{"class":114},[104,337,338],{"class":114}," flutter-install",[104,340,341],{"class":190},"   # copies PorterRx.app to \u002FApplications\n",[343,344,345,348,349,352],"note",{},[101,346,347],{},"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 ",[101,350,351],{},"flutter-build"," mise task strips it.",[78,354,356],{"id":355},"verifying-the-install","Verifying the install",[65,358,359],{},"Send a small text file to yourself:",[94,361,363],{"className":96,"code":362,"language":98,"meta":99,"style":99},"echo \"hello from the other side\" > test.txt\nporter-sender test.txt --slideshow --speed=0.5\n",[101,364,365,386],{"__ignoreMap":99},[104,366,367,370,374,377,380,383],{"class":106,"line":107},[104,368,369],{"class":124},"echo",[104,371,373],{"class":372},"sMK4o"," \"",[104,375,376],{"class":114},"hello from the other side",[104,378,379],{"class":372},"\"",[104,381,382],{"class":372}," >",[104,384,385],{"class":114}," test.txt\n",[104,387,388,390,393,396],{"class":106,"line":121},[104,389,196],{"class":110},[104,391,392],{"class":114}," test.txt",[104,394,395],{"class":114}," --slideshow",[104,397,398],{"class":114}," --speed=0.5\n",[65,400,401],{},"Open the receiver, point it at the terminal, and the file should assemble,\nverify against its SHA-256, and save to Downloads.",[403,404,405],"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 pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}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 .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":99,"searchDepth":121,"depth":121,"links":407},[408,411,412],{"id":80,"depth":121,"text":81,"children":409},[410],{"id":167,"depth":131,"text":168},{"id":221,"depth":121,"text":222},{"id":355,"depth":121,"text":356},"Build the sender binary and install the receiver app.","md",null,{},{"icon":18},{"title":15,"description":413},"sjPKIw1q-haOtqozN5T7xSHuh2Dsnd_Hk1PyZYanxyU",[421,423],{"title":10,"path":11,"stem":12,"description":422,"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":424,"icon":23,"children":-1},"Choosing an encoding, driving the sender, and the three ways to get a file back.",1786321021089]