offsite 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +16 -15
  2. package/apps/server/dist/main.mjs +25 -3
  3. package/apps/server/dist/main.mjs.map +1 -1
  4. package/apps/web/dist/assets/{angular-html-B53hPuXT.js → angular-html-CxKqLP98.js} +1 -1
  5. package/apps/web/dist/assets/{angular-ts--nhprFvo.js → angular-ts-ChaIimso.js} +1 -1
  6. package/apps/web/dist/assets/{apl-BMZ6gSxk.js → apl-C79wKZ96.js} +1 -1
  7. package/apps/web/dist/assets/{astro-BTM15MDF.js → astro-Bjd0-rUa.js} +1 -1
  8. package/apps/web/dist/assets/{blade-Dr8Nx-1X.js → blade-CwnKAXvb.js} +1 -1
  9. package/apps/web/dist/assets/{c-CYWvPMKX.js → c-Z516m-0_.js} +1 -1
  10. package/apps/web/dist/assets/{chapel-C8sB6Foh.js → chapel-CjZ9_INP.js} +1 -1
  11. package/apps/web/dist/assets/{cobol-FnuKKfgs.js → cobol-loY0YFmk.js} +1 -1
  12. package/apps/web/dist/assets/{coffee-DJrh6kIB.js → coffee-UH3lFVdK.js} +1 -1
  13. package/apps/web/dist/assets/{cpp-BLAvrTU1.js → cpp-DglnXsh6.js} +1 -1
  14. package/apps/web/dist/assets/{crystal-BthZctDJ.js → crystal-8bvlXru4.js} +1 -1
  15. package/apps/web/dist/assets/{css-DjklwMwW.js → css-BR1q7k6_.js} +1 -1
  16. package/apps/web/dist/assets/{edge-BunAX5o-.js → edge-BxokJ4MN.js} +1 -1
  17. package/apps/web/dist/assets/{elixir-DgeksfSS.js → elixir-BUaqVZQr.js} +1 -1
  18. package/apps/web/dist/assets/{elm-l1eWnD1P.js → elm-D_9smeEe.js} +1 -1
  19. package/apps/web/dist/assets/{erb-JKFWiSFc.js → erb-DOZIqXQH.js} +1 -1
  20. package/apps/web/dist/assets/{git-rebase-AsNqLj-a.js → git-rebase-DN-oOLvo.js} +1 -1
  21. package/apps/web/dist/assets/{glimmer-js-B8iwahHO.js → glimmer-js-dSW-hX4N.js} +1 -1
  22. package/apps/web/dist/assets/{glimmer-ts-7zfF4XN6.js → glimmer-ts-BgJbFWVH.js} +1 -1
  23. package/apps/web/dist/assets/{glsl-BJka2Ayq.js → glsl-FkhRNxnG.js} +1 -1
  24. package/apps/web/dist/assets/{graphql-7lx4uUDH.js → graphql-BKHVf0BT.js} +1 -1
  25. package/apps/web/dist/assets/{hack-Jm3cv9jc.js → hack-obS7Vybj.js} +1 -1
  26. package/apps/web/dist/assets/{haml-Csl_BhoG.js → haml-8M07SKZy.js} +1 -1
  27. package/apps/web/dist/assets/{handlebars-CFp1rmy8.js → handlebars-Cyb9PeHi.js} +1 -1
  28. package/apps/web/dist/assets/{html-D_zffrV4.js → html-Dwl7QR96.js} +1 -1
  29. package/apps/web/dist/assets/{html-derivative-B-pqZuPW.js → html-derivative-Dx3lESlT.js} +1 -1
  30. package/apps/web/dist/assets/{http-CU_emOoa.js → http-CKSR21d-.js} +1 -1
  31. package/apps/web/dist/assets/{hurl-BRBJ1eQP.js → hurl-DGaDIWma.js} +1 -1
  32. package/apps/web/dist/assets/index-5vPpgW8A.css +2 -0
  33. package/apps/web/dist/assets/index-BJCHT3_X.js +1148 -0
  34. package/apps/web/dist/assets/{java-DWuVSV9c.js → java-BmaAOMbe.js} +1 -1
  35. package/apps/web/dist/assets/{javascript-CPq3YNXl.js → javascript-Dh-l17xw.js} +1 -1
  36. package/apps/web/dist/assets/{jinja-Cwr4gaQT.js → jinja-C14B9X7r.js} +1 -1
  37. package/apps/web/dist/assets/{jison-tIc7kJPc.js → jison-DOLQZnVk.js} +1 -1
  38. package/apps/web/dist/assets/{json-CuLUmV8d.js → json-CKQXRUCT.js} +1 -1
  39. package/apps/web/dist/assets/{jsx-c0vioNM-.js → jsx-D3LXQmFh.js} +1 -1
  40. package/apps/web/dist/assets/{julia-DL1_3nCX.js → julia-BONGpLSW.js} +1 -1
  41. package/apps/web/dist/assets/{just-Dz1Oq8ln.js → just-1ImCRd19.js} +1 -1
  42. package/apps/web/dist/assets/{latex-BtJjjmHB.js → latex-C6nf8qng.js} +1 -1
  43. package/apps/web/dist/assets/{liquid-CUxfxikC.js → liquid-OyHcMLT8.js} +1 -1
  44. package/apps/web/dist/assets/{lua-FURW1z3g.js → lua-CFyXSn73.js} +1 -1
  45. package/apps/web/dist/assets/{marko-D33gqJht.js → marko-w4Xaqrn8.js} +1 -1
  46. package/apps/web/dist/assets/{mdc-rJL-euOm.js → mdc-CipE4q24.js} +1 -1
  47. package/apps/web/dist/assets/{nginx-CChB1oIE.js → nginx-CidGWCuA.js} +1 -1
  48. package/apps/web/dist/assets/{nim-C3VcT8nQ.js → nim-DqvuZ6-V.js} +1 -1
  49. package/apps/web/dist/assets/{org-CX9ySstM.js → org-C8k2emY1.js} +1 -1
  50. package/apps/web/dist/assets/{perl-BmdWqdcq.js → perl-D06UK6ou.js} +1 -1
  51. package/apps/web/dist/assets/{php-CMtd7vHw.js → php-POxwc-vY.js} +1 -1
  52. package/apps/web/dist/assets/{pug-DRlx8d5w.js → pug-BzSRzYD8.js} +1 -1
  53. package/apps/web/dist/assets/{qml-WYwqwy0P.js → qml-DZF7i2J0.js} +1 -1
  54. package/apps/web/dist/assets/{r-C1yAXCUm.js → r-Cem3rJmc.js} +1 -1
  55. package/apps/web/dist/assets/{razor-RKu7WkDv.js → razor-DG8dmRN8.js} +1 -1
  56. package/apps/web/dist/assets/{regexp-DuLU1P7q.js → regexp-B4kXooBf.js} +1 -1
  57. package/apps/web/dist/assets/{rst-CmK0AAXk.js → rst-DKLtDtVi.js} +1 -1
  58. package/apps/web/dist/assets/{ruby-DwgaoIUu.js → ruby-CamS7fke.js} +1 -1
  59. package/apps/web/dist/assets/{sas-iTrXuHXc.js → sas-B0QV8BKG.js} +1 -1
  60. package/apps/web/dist/assets/{scss-CEysq-zA.js → scss-PDWZBsRp.js} +1 -1
  61. package/apps/web/dist/assets/{shellscript-B0mTpBTm.js → shellscript-CdzFXVZ3.js} +1 -1
  62. package/apps/web/dist/assets/{shellsession-BuzD9EVx.js → shellsession-BTvaJuzj.js} +1 -1
  63. package/apps/web/dist/assets/{soy-ClDsFuFk.js → soy-CKjkt_DB.js} +1 -1
  64. package/apps/web/dist/assets/{sql-Dc1h3orO.js → sql-CvyoBOik.js} +1 -1
  65. package/apps/web/dist/assets/{stata-l31dxrtC.js → stata-DKSZtLec.js} +1 -1
  66. package/apps/web/dist/assets/{surrealql-x6LM7pkl.js → surrealql-DLiWChn8.js} +1 -1
  67. package/apps/web/dist/assets/{svelte-CtkYFYuK.js → svelte-BEKUDT0w.js} +1 -1
  68. package/apps/web/dist/assets/{templ-DHMinkR-.js → templ-Cwpj8Ert.js} +1 -1
  69. package/apps/web/dist/assets/{tex-CXbWoQMY.js → tex-eE29FuOr.js} +1 -1
  70. package/apps/web/dist/assets/{ts-tags-BikYq-3m.js → ts-tags-CS_oR42m.js} +1 -1
  71. package/apps/web/dist/assets/{tsx-zHJnYG9T.js → tsx-CXh89N3W.js} +1 -1
  72. package/apps/web/dist/assets/{twig-DKCfiSr9.js → twig-DE2-3Vmd.js} +1 -1
  73. package/apps/web/dist/assets/{typescript-K9TDgxRD.js → typescript-xOdvp9de.js} +1 -1
  74. package/apps/web/dist/assets/{typst-BpXkFpDR.js → typst-B_JeYRUR.js} +1 -1
  75. package/apps/web/dist/assets/{vue-BYYRFXPM.js → vue-dnoj_d3g.js} +1 -1
  76. package/apps/web/dist/assets/{vue-html-BR347tzO.js → vue-html-UHMeN4EH.js} +1 -1
  77. package/apps/web/dist/assets/{vue-vine-Jv4OHYgW.js → vue-vine-Cl2xkrIS.js} +1 -1
  78. package/apps/web/dist/assets/{xml-DuYGU-7M.js → xml-BgkAAaUc.js} +1 -1
  79. package/apps/web/dist/assets/{xsl-B950Zbyt.js → xsl-C4H21Kbc.js} +1 -1
  80. package/apps/web/dist/assets/{yaml-XFYTn8dR.js → yaml-Ce1Tbjry.js} +1 -1
  81. package/apps/web/dist/index.html +2 -2
  82. package/package.json +2 -1
  83. package/apps/web/dist/assets/index-0B-Gdd7b.css +0 -2
  84. package/apps/web/dist/assets/index-CJuLsqhP.js +0 -1148
package/README.md CHANGED
@@ -12,21 +12,22 @@ npx offsite
12
12
 
13
13
  Then open the pairing link it prints. It pairs this browser with the server, so only browsers that opened the link can use it.
14
14
 
15
- | Command | What it does |
16
- | ---------------- | ---------------------------------------------------------------------------------- |
17
- | `offsite` | Starts the server and the web app |
18
- | `offsite web` | Same as `offsite` |
19
- | `offsite serve` | Starts only the server, use it from [offsite.sayad.dev](https://offsite.sayad.dev) |
20
- | `offsite pair` | Makes a pairing token for another browser and prints its links. `--name` labels it |
21
- | `offsite unpair` | Lists paired browsers so you can pick which to unpair |
22
-
23
- | Flag | Default | What it sets |
24
- | ----------- | ------------ | ------------------------------------------------------------ |
25
- | `--host` | `127.0.0.1` | Address to listen on |
26
- | `--port` | `47841` | Port to listen on |
27
- | `--dir` | `~/.offsite` | Folder for settings and accounts |
28
- | `--no-auth` | auth on | Accept connections without the pairing token |
29
- | `--no-pair` | pair on | Don't create a pairing token or print pairing links on start |
15
+ | Command | What it does |
16
+ | ---------------- | ------------------------------------------------------------------------------------------------ |
17
+ | `offsite` | Starts the server and the web app |
18
+ | `offsite web` | Same as `offsite` |
19
+ | `offsite serve` | Starts only the server, use it from [offsite.sayad.dev](https://offsite.sayad.dev) |
20
+ | `offsite pair` | Makes a pairing token for another browser and prints its links and a QR code. `--name` labels it |
21
+ | `offsite unpair` | Lists paired browsers so you can pick which to unpair |
22
+
23
+ | Flag | Default | What it sets |
24
+ | ------------ | ------------ | ---------------------------------------------------------------------------------------- |
25
+ | `--host` | `127.0.0.1` | Address to listen on |
26
+ | `--port` | `47841` | Port to listen on |
27
+ | `--dir` | `~/.offsite` | Folder for settings and accounts |
28
+ | `--no-auth` | auth on | Accept connections without the pairing token |
29
+ | `--no-pair` | pair on | Don't create a pairing token or print pairing links on start |
30
+ | `--fallback` | none | Address the pairing links add for when this one is unreachable, e.g. a Cloudflare tunnel |
30
31
 
31
32
  Pairing tokens stay in `tokens.json` inside `--dir`. A running offsite disconnects an unpaired browser within seconds.
32
33
 
@@ -2,6 +2,7 @@ import { createReadStream, existsSync, lstatSync, mkdirSync, readFileSync, readd
2
2
  import { createServer } from "node:http";
3
3
  import path from "node:path";
4
4
  import { consola } from "consola";
5
+ import { renderUnicodeCompact } from "uqr";
5
6
  import { WebSocketServer } from "ws";
6
7
  import os from "node:os";
7
8
  import { deleteSession, forkSession, getSessionMessages, getSubagentMessages, listSessions, query, renameSession } from "@anthropic-ai/claude-agent-sdk";
@@ -47,7 +48,7 @@ function broadcast(event) {
47
48
  //#region src/args.ts
48
49
  let command = "web";
49
50
  let name = null;
50
- const program = new Command("offsite").description("Starts the server and the web app").option("--host <host>", "Address to listen on", "127.0.0.1").option("--port <port>", "Port to listen on", "47841").option("--dir <dir>", "Folder for settings and accounts", path.join(os.homedir(), ".offsite")).option("--no-auth", "Accept connections without the pairing token").option("--no-pair", "Don't create a pairing token or print pairing links");
51
+ const program = new Command("offsite").description("Starts the server and the web app").option("--host <host>", "Address to listen on", "127.0.0.1").option("--port <port>", "Port to listen on", "47841").option("--dir <dir>", "Folder for settings and accounts", path.join(os.homedir(), ".offsite")).option("--no-auth", "Accept connections without the pairing token").option("--no-pair", "Don't create a pairing token or print pairing links").option("--fallback <url>", "Address to try when this one is unreachable, e.g. a Cloudflare tunnel");
51
52
  program.command("web", { isDefault: true }).description("Starts the server and the web app, same as offsite");
52
53
  program.command("serve").description("Starts only the server, without the web app").action(() => {
53
54
  command = "serve";
@@ -5633,11 +5634,17 @@ if (!Number.isInteger(port) || port < 1 || port > 65535) {
5633
5634
  process.exit(1);
5634
5635
  }
5635
5636
  const address = `http://${args.host}:${port}`;
5637
+ const fallback = args.fallback === void 0 ? null : readFallback(args.fallback);
5636
5638
  if (args.command === "pair") {
5637
5639
  const links = pairingLinks(addToken(args.name));
5638
- console.log("Open one of these links in the browser to pair:");
5639
- console.log(` ${links.local}`);
5640
+ console.log(`Scan this to pair a phone with ${HOSTED_APP}:`);
5641
+ console.log("");
5642
+ console.log(renderUnicodeCompact(links.hosted, { border: 2 }));
5643
+ console.log("");
5644
+ console.log("Or open one of these links in the browser to pair:");
5640
5645
  console.log(` ${links.hosted}`);
5646
+ console.log(` ${links.local}`);
5647
+ if (fallback !== null) console.log(`Fallback: ${fallback}`);
5641
5648
  process.exit(0);
5642
5649
  }
5643
5650
  if (args.command === "unpair") {
@@ -5748,9 +5755,24 @@ async function unpair() {
5748
5755
  removeTokens(picked);
5749
5756
  console.log(`Unpaired ${picked.length} ${picked.length === 1 ? "browser" : "browsers"}; a running offsite disconnects them within seconds`);
5750
5757
  }
5758
+ function readFallback(link) {
5759
+ let url;
5760
+ try {
5761
+ url = new URL(link);
5762
+ } catch {
5763
+ console.error(`invalid fallback URL ${link}`);
5764
+ process.exit(1);
5765
+ }
5766
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
5767
+ console.error(`the fallback URL ${link} needs http:// or https://`);
5768
+ process.exit(1);
5769
+ }
5770
+ return url.origin;
5771
+ }
5751
5772
  function pairingLinks(token) {
5752
5773
  const hosted = new URLSearchParams({
5753
5774
  machine: address,
5775
+ ...fallback !== null && { fallback },
5754
5776
  ...token !== null && { token }
5755
5777
  });
5756
5778
  return {