airpocket 0.0.0-stage → 0.1.0

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 (58) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/LICENSE +21 -0
  3. package/README.md +245 -2
  4. package/SECURITY.md +114 -0
  5. package/package.json +42 -4
  6. package/src/agentconfig.js +300 -0
  7. package/src/behind.js +86 -0
  8. package/src/bridges.js +254 -0
  9. package/src/cli.js +92 -0
  10. package/src/doctor.js +196 -0
  11. package/src/hook.js +198 -0
  12. package/src/loginitem.js +122 -0
  13. package/src/models.js +173 -0
  14. package/src/ownterm.js +299 -0
  15. package/src/ports.js +48 -0
  16. package/src/proc.js +184 -0
  17. package/src/public/app.css +581 -0
  18. package/src/public/app.js +1729 -0
  19. package/src/public/fonts/OFL-B612.txt +93 -0
  20. package/src/public/fonts/OFL-IBM-Plex.txt +93 -0
  21. package/src/public/fonts/b612-400.woff2 +0 -0
  22. package/src/public/fonts/b612-700.woff2 +0 -0
  23. package/src/public/fonts/b612-mono-400.woff2 +0 -0
  24. package/src/public/fonts/b612-mono-700.woff2 +0 -0
  25. package/src/public/fonts/plex-400.woff2 +0 -0
  26. package/src/public/fonts/plex-500.woff2 +0 -0
  27. package/src/public/fonts/plex-600.woff2 +0 -0
  28. package/src/public/icon-180.png +0 -0
  29. package/src/public/icon-512.png +0 -0
  30. package/src/public/icon-maskable-512.png +0 -0
  31. package/src/public/index.html +46 -0
  32. package/src/public/launch/375x667@2.jpg +0 -0
  33. package/src/public/launch/375x812@3.jpg +0 -0
  34. package/src/public/launch/390x844@3.jpg +0 -0
  35. package/src/public/launch/393x852@3.jpg +0 -0
  36. package/src/public/launch/402x874@3.jpg +0 -0
  37. package/src/public/launch/414x736@3.jpg +0 -0
  38. package/src/public/launch/414x896@2.jpg +0 -0
  39. package/src/public/launch/414x896@3.jpg +0 -0
  40. package/src/public/launch/420x912@3.jpg +0 -0
  41. package/src/public/launch/428x926@3.jpg +0 -0
  42. package/src/public/launch/430x932@3.jpg +0 -0
  43. package/src/public/launch/440x956@3.jpg +0 -0
  44. package/src/public/manifest.webmanifest +31 -0
  45. package/src/public/map.svg +1 -0
  46. package/src/public/md.js +162 -0
  47. package/src/public/qr.js +605 -0
  48. package/src/public/sw.js +35 -0
  49. package/src/public/where.js +22 -0
  50. package/src/secrets.js +8 -0
  51. package/src/server.js +1722 -0
  52. package/src/service.js +541 -0
  53. package/src/setup.js +831 -0
  54. package/src/shellalias.js +109 -0
  55. package/src/store.js +122 -0
  56. package/src/tailscale.js +139 -0
  57. package/src/tmux.conf +64 -0
  58. package/src/uploads.js +124 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,56 @@
1
+ # Changelog
2
+
3
+ Every change people using Airpocket would notice, newest first. The form is
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow
5
+ [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## 0.1.0 - 2026-09-17
8
+
9
+ The first version. Airpocket runs on each Mac where you use Claude Code or
10
+ Codex and makes those sessions reachable from a web app on your phone, over
11
+ your own Tailscale network. There is no Airpocket server, account or relay.
12
+ macOS only, Node 20 or newer.
13
+
14
+ ### Added
15
+
16
+ - **One list** of every Claude Code and Codex session on every paired Mac,
17
+ with the ones waiting on you first: finished, waiting for input, needing
18
+ permission. Each row shows the model, effort, permission mode and whether a
19
+ turn is running. Agents running on the Mac that Airpocket hasn't heard from
20
+ yet are counted, with a line on how to bring them in.
21
+ - **The conversation**, read from the agents' own session files rather than the
22
+ terminal: your messages, the replies, and one short label per step, updated
23
+ live. Codex turns are shown while they run.
24
+ - **Reply and control** from the phone: send messages and photos, press keys,
25
+ pick options in on-screen menus, and change model, effort, permission mode
26
+ and fast mode from each agent's own model list. Commands such as compact,
27
+ resume and clear come from a fixed table on the Mac, and are refused while a
28
+ turn runs, a menu is open or unsent text sits in the box.
29
+ - **New sessions** in a project, on a new branch or in an existing workspace,
30
+ for Claude Code or Codex, when Superset is installed.
31
+ - **Files a session wrote, edited or linked**: text, Markdown, code, images,
32
+ PDFs and HTML pages, limited to the session's own folder and checked by
33
+ content. PDFs and pages open from a separate file-only origin through
34
+ two-minute links, and pages there run no scripts.
35
+ - **`airpocket run claude|codex`**: starts the agent in a tmux session of
36
+ Airpocket's own, so the phone can answer a session started in any terminal.
37
+ `airpocket attach` brings back one whose window was closed. Sessions in
38
+ Superset or an existing tmux pane can be answered without it; anything else
39
+ is shown read-only.
40
+ - **`airpocket setup`**: checks the Mac first and stops before changing
41
+ anything if something is missing, then installs the hooks for Claude Code
42
+ and Codex (merged into their settings, with a backup), a login item, the app
43
+ published inside the tailnet with `tailscale serve`, optional `claude` and
44
+ `codex` shell aliases, and a pairing code with its QR. `--dry-run` prints
45
+ the plan.
46
+ - **`airpocket doctor`**: checks the install and says what to do about each
47
+ problem. **`airpocket uninstall`** removes what setup added, taking only its
48
+ own entries out of the agents' config files.
49
+ - **Pairing** with a six-digit code or its QR, one token per phone and per
50
+ Mac, stored on the Mac only as a hash. `airpocket devices` lists paired
51
+ phones and `airpocket revoke` cuts one off at once.
52
+ - **A home-screen web app** with no App Store. It still opens when the Mac
53
+ that served it is asleep, follows Reduce Motion and Reduce Transparency, and
54
+ ships its own fonts.
55
+ - **Security documentation**: [SECURITY.md](SECURITY.md) for reporting a
56
+ problem, and a threat model and review checklist in the repository's `docs`.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Oncel Ozgul
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,246 @@
1
- # Temporary Holding Version
1
+ <h1 align="center"><img src="docs/images/banner.png" width="100%" alt="Airpocket: the dart and the wordmark on a dark chart, over the line &quot;Your agents fly the missions. This is the cockpit.&quot;"></h1>
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ <p align="center">
4
+ <a href="#install-macos">Install</a> ·
5
+ <a href="https://airpocket.sh/#how">How it works</a> ·
6
+ <a href="#security-in-one-paragraph">Security</a> ·
7
+ <a href="https://airpocket.sh/#faq">FAQ</a> ·
8
+ <a href="https://airpocket.sh">airpocket.sh</a> ·
9
+ <a href="https://github.com/airpocket-sh/airpocket/releases">Releases</a>
10
+ </p>
11
+
12
+ <p align="center">
13
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-D7C49E?style=flat-square&labelColor=1B2118" alt="License: MIT"></a>
14
+ <a href="https://github.com/airpocket-sh/airpocket/actions/workflows/test.yml"><img src="https://github.com/airpocket-sh/airpocket/actions/workflows/test.yml/badge.svg?branch=main" alt="Tests on main"></a>
15
+ <img src="https://img.shields.io/badge/platform-macOS-D7C49E?style=flat-square&labelColor=1B2118" alt="Platform: macOS">
16
+ <img src="https://img.shields.io/badge/node-20%2B-D7C49E?style=flat-square&labelColor=1B2118" alt="Node 20 or newer">
17
+ <img src="https://img.shields.io/badge/dependencies-none-8FD14F?style=flat-square&labelColor=1B2118" alt="Dependencies: none">
18
+ </p>
19
+
20
+ Your coding agents, on your phone. Every Claude Code and Codex session on every
21
+ one of your Macs, in one list, with the ones waiting on you first. Read the
22
+ conversation, reply, answer questions, switch models, start new sessions and
23
+ open the files they made, from anywhere.
24
+
25
+ Nothing sits in between: your phone talks to your Macs over your own
26
+ [Tailscale](https://tailscale.com) network. There is no Airpocket server, no
27
+ account and no relay. It works in the terminal you already use. What it needs:
28
+ a Mac with Node 20 or newer and Claude Code or Codex, and Tailscale on the Mac
29
+ and on the phone.
30
+
31
+ <p align="center"><img src="docs/images/phones.png" width="100%" alt="Three phones running Airpocket. First, the session list: three sessions need you (one asking permission to use Bash, one asking which Stripe API version to target, one finished) above two open ones. Second, a session asking &quot;Do you want to proceed?&quot; with three numbered answers and a reply box. Third, a TypeScript file the agent wrote, open with line numbers."></p>
32
+
33
+ > **Status: private, work in progress.** Not on npm yet: to try it, install
34
+ > from a clone (below). See [docs/PLAN.md](docs/PLAN.md), and
35
+ > [CONTRIBUTING.md](CONTRIBUTING.md) to send a change.
36
+
37
+ ## What it will do
38
+
39
+ - **One list** of every session on every paired Mac: needs you, open, earlier.
40
+ - **The conversation**, not the raw terminal: messages, answers, one line per
41
+ step, updated live, including Codex mid-turn.
42
+ - **Reply and control**: send messages, press keys, pick options on screen,
43
+ change model, effort and permission mode, compact, resume and more.
44
+ - **Start sessions** in a project, on a new branch or an existing workspace
45
+ (with Superset).
46
+ - **Open files** a session wrote or linked: text, Markdown, code, images,
47
+ PDFs, pages, under strict rules.
48
+ - **Send a photo**: a screenshot, a whiteboard, the thing on your desk, from
49
+ the phone's camera or its library, with or without a message.
50
+ - **A web app**, added to your home screen. No App Store.
51
+
52
+ <p align="center">
53
+ <img src="site/shots/mfd1-sessions-one-waiting.png" width="280" alt="The session list for one Mac: under Needs you, a Claude Code session needing permission to use Bash and a Codex session asking which Stripe API version to target; under Open, a Claude Code session working, on Opus 5 with high effort.">
54
+ &nbsp;
55
+ <img src="site/shots/mfd3-controls-model-effort.png" width="280" alt="The Controls sheet for a Claude Code session: Opus 5 active and Sonnet 5 picked to apply next, effort set to high, permission mode buttons, and session commands including Compact, Resume and Clear.">
56
+ </p>
57
+
58
+ ## Any terminal
59
+
60
+ It works in the terminal you already use: Terminal, iTerm2, Ghostty, Warp, a VS
61
+ Code or Cursor pane. The one change is how you start the agent:
62
+
63
+ ```sh
64
+ airpocket run claude # instead of claude; anything after the name goes to it
65
+ airpocket run codex resume --last
66
+ airpocket attach # back to one you closed the window on
67
+ ```
68
+
69
+ Setup offers to alias `claude` and `codex` to that, and then you type exactly
70
+ what you typed before. Sessions in Superset or tmux need no change: the phone
71
+ answers them as they are.
72
+
73
+ <p align="center">
74
+ <img src="site/shots/mfd2-question-answered.png" width="280" alt="A Claude Code session on the phone, asking before it runs a shell command: &quot;Do you want to proceed?&quot; with the numbered answers Yes; Yes, and don't ask again for npm test commands; and No, and tell Claude what to do differently. A reply box sits underneath.">
75
+ </p>
76
+
77
+ Why `run` is there: the phone can watch a session from its transcript and hooks
78
+ alone, but to answer one Airpocket has to type into its terminal, and a tmux
79
+ pane or a Superset terminal is what lets it. `run` starts the agent in a tmux
80
+ session of Airpocket's own (its own socket in Airpocket's data folder, never
81
+ your tmux server or `~/.tmux.conf`), tuned to stay out of sight: no status bar,
82
+ no prefix key, Esc with no delay, Shift+Enter, the mouse wheel for scrollback,
83
+ copying to the clipboard. Closing the window doesn't stop the agent: the phone
84
+ can still answer it, and `airpocket attach` brings it back. Inside tmux or
85
+ Superset already, `run` starts the agent there directly.
86
+
87
+ A session started the plain way, outside all of that, still shows on the phone,
88
+ read-only, with a line saying how to bring it in.
89
+
90
+ ## Install (macOS)
91
+
92
+ **Airpocket runs on each Mac whose sessions you want to see.** Install it and
93
+ run setup on every one of them, and pair your phone with each. There is no
94
+ shared server and nothing passes between your Macs: the phone keeps one token
95
+ per Mac and asks each one itself.
96
+
97
+ You need, on each Mac: macOS, Node 20 or newer,
98
+ [Tailscale](https://tailscale.com/download/mac) signed in with **MagicDNS and
99
+ HTTPS certificates turned on for your tailnet**, and Claude Code or Codex. On
100
+ the phone: Tailscale, signed in to the same tailnet. Setup also checks for tmux,
101
+ which `airpocket run` uses (above); if it's missing, `brew install tmux`.
102
+
103
+ ### Which tailnet you land in
104
+
105
+ Tailscale sorts people by the email domain they sign in with, so signing in
106
+ with a **work address puts you in your company's tailnet**, not one of your
107
+ own. There you are a member: an admin has to approve your device, the admin
108
+ console won't open for you, and MagicDNS and HTTPS certificates — both
109
+ tailnet-wide, both needed here — are someone else's switch to flip. Setup stops
110
+ with that in plain words rather than half-installing.
111
+
112
+ Signing in with a **personal account** gives you your own tailnet where you are
113
+ the admin, and turning HTTPS certificates on is one switch on the
114
+ [DNS page](https://console.tailscale.com/admin/dns). Either is fine — a shared
115
+ tailnet only needs its admin to do it once, for everyone. Issuing a certificate
116
+ publishes the machine's DNS name in public certificate-transparency logs; what
117
+ it serves stays inside your tailnet.
118
+
119
+ Sharing a tailnet doesn't share sessions: every Mac still asks the phone for a
120
+ pairing code of its own, and hands out its own token.
121
+
122
+ ### Try it from a clone
123
+
124
+ Airpocket isn't on npm yet. Until it is, install it from a clone:
125
+
126
+ ```sh
127
+ git clone https://github.com/airpocket-sh/airpocket.git
128
+ cd airpocket
129
+ npm install -g . # puts the airpocket command on your PATH; no dependencies
130
+ airpocket setup --dry-run # every change it would make; changes nothing
131
+ airpocket setup
132
+ ```
133
+
134
+ `npm install -g .` links the command to your clone. Setup copies Airpocket
135
+ into its data folder and runs that copy (see
136
+ [Keeping it up to date](#keeping-it-up-to-date)).
137
+
138
+ Setup checks first and stops with a plain explanation if something is
139
+ missing. Then it:
140
+
141
+ - adds Airpocket's hooks to `~/.claude/settings.json` and `~/.codex/hooks.json`
142
+ (or under `$CLAUDE_CONFIG_DIR` and `$CODEX_HOME`). It merges: every other
143
+ setting and hook stays as it was, a timestamped backup is written next to the
144
+ file first, and a file that isn't valid JSON is left alone. Running it again
145
+ adds nothing twice.
146
+ - adds a login item (`~/Library/LaunchAgents/sh.airpocket.service.plist`) that
147
+ starts Airpocket at login and brings it back after a crash. It runs the copy
148
+ of Airpocket kept in its data folder, not your clone, so moving or deleting
149
+ the clone doesn't stop it.
150
+ - publishes the app and its file-only origin inside your tailnet with
151
+ `tailscale serve` (never `funnel`), on ports nothing else uses: 443 and
152
+ 8443 when they are free.
153
+ - asks whether to add two aliases to your shell profile (`~/.zshrc` or
154
+ `~/.bash_profile`), so `claude` and `codex` start where the phone can
155
+ answer them (above). `--alias` or `--no-alias` decides without asking.
156
+ Marked, backed up first, and removed by uninstall.
157
+ - prints a pairing code and its QR.
158
+
159
+ Codex asks you to review new hooks the next time it starts: choose to trust
160
+ Airpocket's, or open `/hooks`. A Codex session shows up on the phone once
161
+ you've sent it a first message. In Superset it's different: Superset's `codex`
162
+ wrapper starts Codex with the trust check bypassed, so the hooks run there
163
+ without the review (and the phone's "not trusted yet" line is about Codex
164
+ started anywhere else).
165
+
166
+ Claude Code picks up the hooks while it runs, so sessions started before setup
167
+ need no restart: each appears the next time you prompt it. Codex reads its
168
+ hooks only when it starts, so restart a Codex session that was running before
169
+ setup. Until then the phone says how many Claude Code and how many Codex
170
+ agents are running that haven't checked in, and whether Codex's hooks still
171
+ need trusting; setup prints the same when it finishes.
172
+
173
+ ```sh
174
+ airpocket doctor # checks everything, says what to do; exits 1 if something is broken
175
+ airpocket pair # a new pairing code
176
+ airpocket devices # paired phones; airpocket revoke <id> cuts one off
177
+ airpocket uninstall # removes exactly what setup added; asks before deleting paired phones
178
+ ```
179
+
180
+ **Tested so far:** setup, doctor and uninstall against a temporary home folder
181
+ (with the real launchd in a trial), Claude Code end to end with real
182
+ sessions, and Codex against recorded session files and a real Codex's hooks
183
+ (installed, trusted, firing). Codex with real model replies driven from the
184
+ phone has not been run end to end yet. `airpocket run` with a real Claude in a
185
+ hidden terminal window (keys, paste, resize, scrollback, detach and attach).
186
+
187
+ ### Keeping it up to date
188
+
189
+ ```sh
190
+ cd airpocket
191
+ git pull
192
+ airpocket setup
193
+ ```
194
+
195
+ The `airpocket` command runs from your clone, but the service, the hooks and
196
+ the login item run the copy setup made in the data folder. A `git pull` alone
197
+ changes the command and nothing else; running setup again replaces the copy
198
+ and restarts the service on it. Paired phones stay paired; the pairing code
199
+ setup prints at the end can be ignored.
200
+
201
+ `airpocket doctor` warns when the version the service runs differs from the
202
+ command's. It compares the version numbers in `package.json`, so a pull that
203
+ doesn't change the version passes unnoticed: run setup after every pull.
204
+
205
+ ## Photos
206
+
207
+ The message box has a photo button. Pick from the library or take one, up to
208
+ four to a message, and send it with or without words.
209
+
210
+ The phone shrinks each photo to 2200px and re-encodes it before it goes, which
211
+ also drops what the camera wrote into the file, the place it was taken
212
+ included. The Mac keeps it in Airpocket's own data folder
213
+ (`~/Library/Application Support/Airpocket/uploads`, 0600), never in the project
214
+ the agent is working in, and types the path into the session as part of your
215
+ message, so the agent reads it with the tools it already has. Photos are
216
+ deleted after a week, and only the last forty are kept.
217
+
218
+ Because they sit outside the project, the agent may ask before reading one —
219
+ answer that from the phone like any other prompt. To stop it asking, allow that
220
+ one folder in `~/.claude/settings.json`:
221
+
222
+ ```json
223
+ { "permissions": { "allow": ["Read(//Users/you/Library/Application Support/Airpocket/uploads/**)"] } }
224
+ ```
225
+
226
+ ## Security in one paragraph
227
+
228
+ Airpocket listens on 127.0.0.1 and is published only inside your tailnet. Each
229
+ phone gets its own token for a one-time pairing code; the Mac keeps only
230
+ hashes. The phone never sends a file path or command text: it names a session
231
+ and an action, and the Mac looks up the rest in its own records. Files are
232
+ limited to what a session made or mentioned, inside its own folder, checked by
233
+ content, and PDFs and pages open from a separate file-only origin through
234
+ two-minute links.
235
+
236
+ **Know this before you pair.** A paired phone can type anything into your
237
+ agents, including shell commands (in Claude Code and Codex, a message that
238
+ starts with `!` runs as one), and start new sessions. Its token doesn't expire:
239
+ it works until you revoke it on that Mac. `airpocket devices` lists the paired
240
+ phones, and `airpocket revoke <id>` cuts one off at once. Pair only phones you
241
+ control, and revoke a lost one straight away.
242
+
243
+ ## License
244
+
245
+ MIT. The fonts in `src/public/fonts` (B612, B612 Mono, IBM Plex Sans) are under the
246
+ SIL Open Font License; their licences sit next to them.
package/SECURITY.md ADDED
@@ -0,0 +1,114 @@
1
+ # Security policy
2
+
3
+ Airpocket lets a phone read and type into coding agents on your Macs, so its
4
+ security matters more than its size suggests. Thank you for looking.
5
+
6
+ ## Reporting a vulnerability
7
+
8
+ **Please don't open a public issue, discussion or pull request for a security
9
+ problem.**
10
+
11
+ Report it privately through GitHub: on this repository, open the **Security**
12
+ tab and choose **Report a vulnerability**. Only the maintainers can see the
13
+ report and the conversation that follows.
14
+
15
+ If that route isn't open to you — GitHub only offers it on a public
16
+ repository, and not everyone wants a GitHub account to report a bug — email
17
+ **info@airpocket.sh** instead. It reaches the same people.
18
+
19
+ A good report says:
20
+
21
+ - what the problem is, and what someone could do with it;
22
+ - where it is (file, function, route or command);
23
+ - the version or commit you tested;
24
+ - how to see it happen on your own Mac, phone and tailnet.
25
+
26
+ Leave out real device tokens, pairing codes, hook secrets, tailnet names,
27
+ email addresses and anyone's conversations or files. Replace them with
28
+ placeholders.
29
+
30
+ ## What to expect
31
+
32
+ - **Within 7 days:** we confirm we received the report.
33
+ - **Within 14 days:** a first assessment: in scope or not, how serious, and
34
+ what happens next.
35
+ - **Until it's fixed:** an update at least every 14 days.
36
+ - **A fix** as soon as its severity calls for it, released with a GitHub
37
+ security advisory that describes the problem and the fix.
38
+ - **Disclosure:** please keep the details private until the advisory is out,
39
+ or 90 days after your report, whichever comes first. If a fix needs longer,
40
+ we'll ask you and agree on a date together.
41
+ - **Credit** in the advisory, under the name you choose, if you want it.
42
+
43
+ Airpocket is a free project. There is no bug bounty.
44
+
45
+ ## Supported versions
46
+
47
+ Only the latest release gets security fixes. Fixes are not backported. Until
48
+ the first release, that means the `main` branch.
49
+
50
+ ## Scope
51
+
52
+ In scope:
53
+
54
+ - The Airpocket service: the phone app server and its API, the file-only
55
+ server and the hook endpoint.
56
+ - The hook (`src/hook.js`), the `airpocket` command, and the setup and
57
+ uninstall steps once they ship.
58
+ - The phone web app (`src/public`).
59
+ - Anything that breaks a promise in [docs/THREAT-MODEL.md](docs/THREAT-MODEL.md)
60
+ or in the posture below. For example: reaching the API without a valid
61
+ token; opening a file outside the file rules; typing into a terminal that
62
+ isn't the agent's; a token, secret or file's contents in a log; data leaving
63
+ the user's own machines.
64
+
65
+ Out of scope:
66
+
67
+ - A Mac account that is already compromised, including any process running as
68
+ that user.
69
+ - Physical access to an unlocked phone.
70
+ - What a user's own agent chooses to do.
71
+ - Bugs in Tailscale, Claude Code, Codex, Superset, tmux, macOS or iOS. Please
72
+ report those to their makers. If Airpocket *uses* one of them unsafely, that
73
+ is in scope.
74
+ - Setups Airpocket doesn't make: `tailscale funnel`, listening on addresses
75
+ other than 127.0.0.1, another proxy in front of it.
76
+ - Denial of service by someone already on your tailnet or your Mac.
77
+ - The residual risks already listed in the threat model, unless you show one
78
+ is worse than written there.
79
+
80
+ When testing, use only Macs, phones and tailnets that are yours. Don't read,
81
+ change or keep other people's data; if you come across any, stop and tell us.
82
+ We won't pursue anyone who follows this policy in good faith.
83
+
84
+ ## Standing posture
85
+
86
+ These hold for every release. A change that breaks one of them won't be
87
+ accepted.
88
+
89
+ - **Tailnet only.** Every server listens on 127.0.0.1. `airpocket setup`
90
+ publishes the app and the file-only origin with `tailscale serve`, which
91
+ reaches only devices on your tailnet. Airpocket never uses `tailscale
92
+ funnel` and never publishes anything to the public internet. The hook
93
+ endpoint is never published at all.
94
+ - **No cloud.** There is no Airpocket server, relay or hosted service. Your
95
+ phone talks straight to your Macs over your own Tailscale network.
96
+ - **No account.** Nothing to sign up for. Each phone pairs with each Mac using
97
+ a short-lived code shown on that Mac, and gets its own token; the Mac keeps
98
+ only a hash of it.
99
+ - **Nothing leaves your machines.** Airpocket has no telemetry, analytics,
100
+ crash reporting or update checks, and makes no network requests except
101
+ between your phone and your Macs. Your conversations, files and tokens stay
102
+ on your devices. Your agents still talk to their own providers, as they do
103
+ without Airpocket, and Tailscale's coordination service knows which devices
104
+ you have, not what they send.
105
+ - **The phone asks, the Mac decides.** The phone names a session and an
106
+ action. It never sends a file path, a terminal, or the text of a Controls
107
+ command; the Mac looks those up in its own records and fixed tables.
108
+ - **One way in, one place to land.** The only thing a phone can put on the Mac
109
+ is a photo for a session, and it lands in Airpocket's own data folder, 0600,
110
+ never in a project. The bytes have to be an image the agents can read, the
111
+ phone gets a ref rather than a path, and old photos are swept.
112
+
113
+ How Airpocket defends each of these, and what it knowingly doesn't, is in
114
+ [docs/THREAT-MODEL.md](docs/THREAT-MODEL.md).
package/package.json CHANGED
@@ -1,6 +1,44 @@
1
1
  {
2
2
  "name": "airpocket",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "Your Claude Code and Codex sessions, from every Mac, on your phone.",
5
+ "keywords": [
6
+ "claude-code",
7
+ "codex",
8
+ "tailscale",
9
+ "iphone",
10
+ "terminal",
11
+ "agents",
12
+ "macos"
13
+ ],
14
+ "homepage": "https://airpocket.sh",
15
+ "bugs": {
16
+ "url": "https://github.com/airpocket-sh/airpocket/issues"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/airpocket-sh/airpocket.git"
21
+ },
22
+ "license": "MIT",
23
+ "author": "Oncel Ozgul",
24
+ "main": "src/server.js",
25
+ "bin": {
26
+ "airpocket": "src/cli.js"
27
+ },
28
+ "files": [
29
+ "src/",
30
+ "SECURITY.md",
31
+ "CHANGELOG.md"
32
+ ],
33
+ "os": [
34
+ "darwin"
35
+ ],
36
+ "engines": {
37
+ "node": ">=20"
38
+ },
39
+ "scripts": {
40
+ "start": "node src/server.js",
41
+ "test": "node --test",
42
+ "smoke": "node .github/smoke.js"
43
+ }
44
+ }