smsforwarder 1.0.0 → 1.2.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.
package/README.md CHANGED
@@ -7,14 +7,14 @@ Install [SMS Forwarder](https://smsforwarder.app/download/) on the phone that re
7
7
  ```sh
8
8
  npm install -g smsforwarder
9
9
  smsforwarder login sk_your_key
10
- CODE=$(smsforwarder code --from GitHub --timeout 90)
10
+ CODE=$(smsforwarder code --timeout 90)
11
11
  ```
12
12
 
13
- `code` waits until a matching code arrives and prints only the code. It exits with status 2 if nothing arrives in time.
13
+ `code` waits for the newest text to arrive and prints its code. If no code was recognised in the text, it prints the whole text instead (and says so on stderr), so nothing is lost. It exits with status 2 if nothing arrives in time. If other texts arrived in the same window it says so on stderr; `smsforwarder messages` lists them in full so you can pick by the text.
14
14
 
15
15
  ```
16
- smsforwarder code [--from x] [--contains x] [--timeout sec] [--json]
17
- smsforwarder messages [--from x] [--limit n] [--codes] [--json]
16
+ smsforwarder code [--timeout sec] [--since time] [--json]
17
+ smsforwarder messages [--minutes n] [--limit n] [--json]
18
18
  smsforwarder devices
19
19
  smsforwarder webhook set <url> | rm | test
20
20
  smsforwarder mcp # MCP config for Claude, Cursor and other AI tools
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smsforwarder",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Get SMS verification codes from your own phone in scripts and AI agents. CLI for SMS Forwarder (smsforwarder.app).",
5
5
  "type": "module",
6
6
  "bin": { "smsforwarder": "smsforwarder.mjs" },
package/smsforwarder.mjs CHANGED
@@ -11,13 +11,12 @@ const HELP = `SMS Forwarder — verification codes from your phone, in your term
11
11
 
12
12
  Usage:
13
13
  smsforwarder login <api-key> Save your API key (from the phone app)
14
- smsforwarder code [options] Wait for the next verification code and print it
15
- --from <text> Only codes from this service / sender (e.g. Google, 淘宝)
16
- --contains <text> Only messages containing this text
14
+ smsforwarder code [options] Wait for the newest text and print its code, or the whole text if no code was recognised
17
15
  --timeout <sec> How long to wait, max 120 (default 60)
18
16
  --since <time> Only messages after this ISO time / unix ms (default: 2 minutes ago)
19
- --json Print the whole message as JSON
20
- smsforwarder messages [--from x] [--contains x] [--limit n] [--codes] [--json]
17
+ --json Print the whole result as JSON, including every other message from the same window
18
+ smsforwarder messages [--minutes n] [--limit n] [--json]
19
+ Messages from the last n minutes (default 10), newest first
21
20
  smsforwarder devices List connected phones
22
21
  smsforwarder webhook set <url> Send every new message to your URL (prints the signing secret)
23
22
  smsforwarder webhook rm Stop sending to the webhook
@@ -58,7 +57,7 @@ function apiKey() {
58
57
  async function call(method, path, body) {
59
58
  const res = await fetch(API + path, {
60
59
  method,
61
- headers: { authorization: `Bearer ${apiKey()}`, "content-type": "application/json", "user-agent": "smsforwarder-cli/1.0.0" },
60
+ headers: { authorization: `Bearer ${apiKey()}`, "content-type": "application/json", "user-agent": "smsforwarder-cli/1.1.0" },
62
61
  body: body ? JSON.stringify(body) : undefined,
63
62
  });
64
63
  const data = await res.json().catch(() => ({}));
@@ -83,6 +82,10 @@ function ago(iso) {
83
82
 
84
83
  const { pos, opt } = parse(process.argv.slice(2));
85
84
  const cmd = pos[0];
85
+ for (const gone of ["from", "contains"]) {
86
+ if (opt[gone] !== undefined) die(`--${gone} is gone: who sends a code can't be predicted. Take the newest code, or list recent messages and pick by text.`);
87
+ }
88
+ if (opt.codes !== undefined) die("--codes is gone: some codes can't be picked out of the text, so every message is listed in full.");
86
89
 
87
90
  switch (cmd) {
88
91
  case "login": {
@@ -98,14 +101,24 @@ switch (cmd) {
98
101
  case "code":
99
102
  case "wait": {
100
103
  const timeout = Math.min(Number(opt.timeout ?? 60) || 60, 120);
101
- const { status, data } = await call("GET", "/v1/codes/wait" + qs({ from: opt.from, contains: opt.contains, since: opt.since, timeout }));
102
- if (status === 404 || !data.code) die(`No code arrived within ${timeout}s.`, 2);
103
- console.log(opt.json ? JSON.stringify(data.message, null, 2) : data.code);
104
+ const { status, data } = await call("GET", "/v1/codes/wait" + qs({ since: opt.since, timeout }));
105
+ if (status === 404 || !data.message) die(`No message arrived within ${timeout}s.`, 2);
106
+ if (opt.json) console.log(JSON.stringify(data, null, 2));
107
+ else {
108
+ if (data.code) console.log(data.code);
109
+ else {
110
+ console.log(data.message.body);
111
+ process.stderr.write("No code was recognised in this text, so the whole text is printed above.\n");
112
+ }
113
+ if (data.otherMessages?.length) {
114
+ process.stderr.write(`${data.otherMessages.length} other message(s) arrived in the same window; run \`smsforwarder messages\` to pick by text.\n`);
115
+ }
116
+ }
104
117
  break;
105
118
  }
106
119
  case "messages":
107
120
  case "ls": {
108
- const { data } = await call("GET", "/v1/messages" + qs({ from: opt.from, contains: opt.contains, limit: opt.limit ?? 20, codes_only: opt.codes ? "true" : undefined }));
121
+ const { data } = await call("GET", "/v1/messages" + qs({ minutes: opt.minutes ?? 10, limit: opt.limit ?? 20 }));
109
122
  if (opt.json) {
110
123
  console.log(JSON.stringify(data.messages, null, 2));
111
124
  break;
@@ -113,7 +126,7 @@ switch (cmd) {
113
126
  if (!data.messages.length) console.log("No messages yet.");
114
127
  for (const m of data.messages) {
115
128
  const who = m.service || m.from || "?";
116
- console.log(`${ago(m.receivedAt).padEnd(8)} ${who}${m.code ? ` [${m.code}]` : ""}\n ${m.body.replace(/\s+/g, " ").slice(0, 160)}`);
129
+ console.log(`${ago(m.receivedAt).padEnd(8)} ${who}${m.code ? ` [${m.code}]` : ""}\n ${m.body.replace(/\s+/g, " ")}`);
117
130
  }
118
131
  break;
119
132
  }