[{"data":1,"prerenderedAt":675},["ShallowReactive",2],{"navigation_docs":3,"-docs-getting-started-using-porter":59,"-docs-getting-started-using-porter-surround":670},[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":20,"body":61,"description":663,"extension":664,"links":665,"meta":666,"navigation":667,"path":21,"seo":668,"stem":22,"__hash__":669},"docs\u002Fdocs\u002F1.getting-started\u002F3.using-porter.md",{"type":62,"value":63,"toc":648},"minimark",[64,93,97,102,105,179,182,189,193,196,325,330,334,340,409,412,418,430,434,444,451,466,470,473,488,496,500,503,511,529,544,551,611,637,644],[65,66,71],"pre",{"className":67,"code":68,"language":69,"meta":70,"style":70},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","porter-sender myfile.pdf --fountain --slideshow\n","bash","",[72,73,74],"code",{"__ignoreMap":70},[75,76,79,83,87,90],"span",{"class":77,"line":78},"line",1,[75,80,82],{"class":81},"sBMFI","porter-sender",[75,84,86],{"class":85},"sfazB"," myfile.pdf",[75,88,89],{"class":85}," --fountain",[75,91,92],{"class":85}," --slideshow\n",[94,95,96],"p",{},"Open the receiver, point it at the terminal. That is the common case — the rest\nof this page is what the flags do and when they matter.",[98,99,101],"h2",{"id":100},"sequential-or-fountain","Sequential or fountain",[94,103,104],{},"This is the one decision worth making deliberately.",[106,107,108,127],"table",{},[109,110,111],"thead",{},[112,113,114,117,120],"tr",{},[115,116],"th",{},[115,118,119],{},"Sequential (default)",[115,121,122,123,126],{},"Fountain (",[72,124,125],{},"--fountain",")",[128,129,130,146,157,168],"tbody",{},[112,131,132,136,141],{},[133,134,135],"td",{},"Frame",[133,137,138],{},[72,139,140],{},"index|total|mode|id|payload",[133,142,143],{},[72,144,145],{},"F|seq|K|fileSize|id|payload",[112,147,148,151,154],{},[133,149,150],{},"A missed frame",[133,152,153],{},"Wait for the sender to loop back to that index",[133,155,156],{},"Costs nothing — catch a different one",[112,158,159,162,165],{},[133,160,161],{},"Frames needed",[133,163,164],{},"Exactly the ones you're missing",[133,166,167],{},"~1.33×–1.89× K, any of them",[112,169,170,173,176],{},[133,171,172],{},"Good for",[133,174,175],{},"Small files, good light, a steady hand",[133,177,178],{},"Long transfers, poor light, handheld scanning",[94,180,181],{},"Sequential is fine for a few hundred chunks. Past that, one frame your camera\nconsistently misses — a glare spot, a blur at the same point in every loop —\nstalls the whole transfer, and fountain is worth the overhead.",[183,184,185,188],"note",{},[72,186,187],{},"--base64"," has no effect in fountain mode; fountain payloads are always base64.",[98,190,192],{"id":191},"driving-the-slideshow","Driving the slideshow",[94,194,195],{},"The sender is a full TUI: a QR grid, a sidebar showing chunk, progress, QR\nversion, ETA, elapsed time and loop count, and a status line.",[106,197,198,208],{},[109,199,200],{},[112,201,202,205],{},[115,203,204],{},"Key",[115,206,207],{},"Action",[128,209,210,230,246,262,272,282,295,305,315],{},[112,211,212,227],{},[133,213,214,217,218,217,221,217,224],{},[72,215,216],{},"→"," ",[72,219,220],{},"l",[72,222,223],{},"k",[72,225,226],{},"space",[133,228,229],{},"Next frame",[112,231,232,243],{},[133,233,234,217,237,217,240],{},[72,235,236],{},"←",[72,238,239],{},"h",[72,241,242],{},"j",[133,244,245],{},"Previous frame",[112,247,248,259],{},[133,249,250,253,254,256,257],{},[72,251,252],{},"Shift","+",[72,255,236],{},"\u002F",[72,258,216],{},[133,260,261],{},"Scrub ~100 chunks",[112,263,264,269],{},[133,265,266],{},[72,267,268],{},"J",[133,270,271],{},"Jump to a specific chunk",[112,273,274,279],{},[133,275,276],{},[72,277,278],{},"G",[133,280,281],{},"Gap-fill mode — loop only the indices you name",[112,283,284,292],{},[133,285,286,288,289],{},[72,287,253],{}," \u002F ",[72,290,291],{},"-",[133,293,294],{},"Faster \u002F slower",[112,296,297,302],{},[133,298,299],{},[72,300,301],{},"S",[133,303,304],{},"Toggle slideshow",[112,306,307,312],{},[133,308,309],{},[72,310,311],{},"I",[133,313,314],{},"Toggle the sidebar",[112,316,317,322],{},[133,318,319],{},[72,320,321],{},"Q",[133,323,324],{},"Quit",[94,326,327,329],{},[72,328,278],{}," is the sequential-mode rescue: when the receiver reports missing chunks\n4,102 and 9,887, loop just those instead of the whole file again.",[98,331,333],{"id":332},"speed","Speed",[94,335,336,339],{},[72,337,338],{},"--speed"," is the delay between frames in seconds. The default works essentially\neverywhere; going faster trades reliability for time.",[106,341,342,355],{},[109,343,344],{},[112,345,346,349,352],{},[115,347,348],{},"Value",[115,350,351],{},"Rate",[115,353,354],{},"Conditions",[128,356,357,370,383,396],{},[112,358,359,364,367],{},[133,360,361],{},[72,362,363],{},"0.5",[133,365,366],{},"2\u002Fsec",[133,368,369],{},"Default — works everywhere",[112,371,372,377,380],{},[133,373,374],{},[72,375,376],{},"0.3",[133,378,379],{},"3.3\u002Fsec",[133,381,382],{},"Good lighting",[112,384,385,390,393],{},[133,386,387],{},[72,388,389],{},"0.2",[133,391,392],{},"5\u002Fsec",[133,394,395],{},"Bright light, steady hand",[112,397,398,403,406],{},[133,399,400],{},[72,401,402],{},"0.1",[133,404,405],{},"10\u002Fsec",[133,407,408],{},"Optimal only",[94,410,411],{},"Dropped frames cost more than a slow rate does in sequential mode. In fountain\nmode they cost almost nothing, so push harder there.",[94,413,414,417],{},[72,415,416],{},"--multi=N"," renders up to four QR codes per frame in a grid, multiplying\nthroughput if the camera can resolve them all. A larger terminal also means a\nhigher QR version and more bytes per code, so a maximised window is free\nthroughput.",[419,420,421,422,425,426,429],"warning",{},"Resizing the terminal mid-transfer changes the QR version, which changes ",[72,423,424],{},"K"," and\n",[72,427,428],{},"blockSize"," — forking the stream into one the receiver can't merge with what it\nalready has. Size the window before you start.",[98,431,433],{"id":432},"binary-files-and-verification","Binary files and verification",[94,435,436,437,439,440,443],{},"Binary input is detected automatically and switches on base64; ",[72,438,187],{}," forces\nit. ",[72,441,442],{},"--verify=\u003Cfile>"," checks the input against an existing SHA-256 file before\nsending.",[94,445,446,447,450],{},"Fountain transfers always end with a ",[72,448,449],{},"CHECKSUM"," frame, so the receiver verifies\nby default. Sequential transfers only send one when you ask.",[94,452,453,454,457,458,461,462,465],{},"By default the sender writes nothing to disk. ",[72,455,456],{},"--resume"," opts into persisting\nslideshow position in ",[72,459,460],{},".porter_history","; ",[72,463,464],{},"--reset"," ignores a saved position\nwithout discarding the file.",[98,467,469],{"id":468},"receiving","Receiving",[94,471,472],{},"Scanning starts automatically — there is no button and no session to establish,\nbecause the sender does not know you exist. Each decoded payload is parsed,\nhanded to a worker isolate, and written to disk as it resolves. On completion\nthe app verifies SHA-256 and saves to Downloads.",[419,474,475,476,478,479,481,482,484,485,487],{},"Fountain progress is not linear against ",[72,477,424],{},". Peeling needs materially more than\n",[72,480,424],{}," distinct symbols — 1.33× to 1.89× across real transfers — so a bar scaled to\n",[72,483,424],{}," sits at 99% with a third of the scanning left. The app scales to ~2×",[72,486,424],{},".",[94,489,490,491,495],{},"Chunks are written to disk as they decode, one file per recovered block. If the\napp is killed, it rehydrates from those files on the next launch — no re-scanning\nwhat you already caught. Hydration trusts the ",[492,493,494],"strong",{},"chunk filenames",", not the\nmetadata file, which is debounced and can lag what is actually on disk.",[98,497,499],{"id":498},"without-a-camera","Without a camera",[94,501,502],{},"Two subcommands finish a transfer when the bytes are already somewhere useful.",[504,505,507,510],"h3",{"id":506},"serve-over-a-network",[72,508,509],{},"serve"," — over a network",[65,512,514],{"className":67,"code":513,"language":69,"meta":70,"style":70},"porter-sender serve --port=8080 --output-dir=received\n",[72,515,516],{"__ignoreMap":70},[75,517,518,520,523,526],{"class":77,"line":78},[75,519,82],{"class":81},[75,521,522],{"class":85}," serve",[75,524,525],{"class":85}," --port=8080",[75,527,528],{"class":85}," --output-dir=received\n",[94,530,531,532,535,536,539,540,543],{},"An HTTP receiver on ",[72,533,534],{},"axum",". ",[72,537,538],{},"POST \u002Fupload"," accepts raw bodies,\n",[72,541,542],{},"multipart\u002Fform-data",", and QR-scan JSON — sequential, fountain and checksum\nframes alike — and auto-joins completed transfers.",[504,545,547,550],{"id":546},"join-from-parts-on-disk",[72,548,549],{},"join"," — from parts on disk",[65,552,554],{"className":67,"code":553,"language":69,"meta":70,"style":70},"porter-sender join \u003Ctransfer-dir|file|id> [--output \u003Cpath>] [--force] [--no-verify]\n",[72,555,556],{"__ignoreMap":70},[75,557,558,560,563,567,570,573,576,578,581,585,588,591,593,596,599,602,605,608],{"class":77,"line":78},[75,559,82],{"class":81},[75,561,562],{"class":85}," join",[75,564,566],{"class":565},"sMK4o"," \u003C",[75,568,569],{"class":85},"transfer-dir",[75,571,572],{"class":565},"|",[75,574,575],{"class":81},"file",[75,577,572],{"class":565},[75,579,580],{"class":81},"id",[75,582,584],{"class":583},"sTEyZ","> [--output ",[75,586,587],{"class":565},"\u003C",[75,589,590],{"class":85},"pat",[75,592,239],{"class":583},[75,594,595],{"class":565},">",[75,597,598],{"class":85},"]",[75,600,601],{"class":583}," [--force] ",[75,603,604],{"class":565},"[",[75,606,607],{"class":583},"--no-verify",[75,609,610],{"class":565},"]\n",[94,612,613,614,617,618,621,622,625,626,629,630,633,634,487],{},"Reassembles the ",[72,615,616],{},".partaa",", ",[72,619,620],{},".partab",", … files a receiver wrote, verifying against\n",[72,623,624],{},"\u003Cbase>.sha256"," when one is present. The target can be a transfer directory, any\nfile inside one, or a bare transfer id. Output goes to ",[72,627,628],{},"\u003Cbase>.joined"," unless\n",[72,631,632],{},"--output"," says otherwise; an existing destination is never overwritten without\n",[72,635,636],{},"--force",[183,638,639,640,643],{},"Stray files that merely share a ",[72,641,642],{},".part"," prefix are skipped rather than\nconcatenated in — a deliberate difference from the TypeScript implementation this\nwas ported from.",[645,646,647],"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 .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}",{"title":70,"searchDepth":649,"depth":649,"links":650},2,[651,652,653,654,655,656],{"id":100,"depth":649,"text":101},{"id":191,"depth":649,"text":192},{"id":332,"depth":649,"text":333},{"id":432,"depth":649,"text":433},{"id":468,"depth":649,"text":469},{"id":498,"depth":649,"text":499,"children":657},[658,661],{"id":506,"depth":659,"text":660},3,"serve — over a network",{"id":546,"depth":659,"text":662},"join — from parts on disk","Choosing an encoding, driving the sender, and the three ways to get a file back.","md",null,{},{"icon":23},{"title":20,"description":663},"QiTutLzTvSuT-zW3rYw5pNvkmRlJXZqzRzFFdRxiuLE",[671,673],{"title":15,"path":16,"stem":17,"description":672,"icon":18,"children":-1},"Build the sender binary and install the receiver app.",{"title":31,"path":32,"stem":33,"description":674,"icon":34,"children":-1},"The two programs, the one-way link between them, and where each stage of a transfer happens.",1786373778113]