inbox-to-md 0.1.0 → 0.1.1
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 +49 -19
- package/dist/account-auth.d.ts +14 -0
- package/dist/account-auth.js +71 -0
- package/dist/account-auth.js.map +1 -0
- package/dist/auth.js +6 -46
- package/dist/auth.js.map +1 -1
- package/dist/authcli.d.ts +1 -0
- package/dist/authcli.js +189 -0
- package/dist/authcli.js.map +1 -0
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,43 +1,73 @@
|
|
|
1
1
|
# inbox-to-md
|
|
2
2
|
|
|
3
|
-
Sync IMAP inboxes to Markdown files — one file per email
|
|
3
|
+
Sync IMAP inboxes to Markdown files and compacts them for agent use — one file per email.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Agent skill
|
|
6
|
+
|
|
7
|
+
This tool is designed to be used by agents. The repo includes a [`hello` skill](SKILL.md) that shows how an agent can install and use `inbox-to-md` to sync and compact mail, then turn the resulting digests into a personalized greeting and task summary. Please use that!
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## Install and run
|
|
11
|
+
|
|
12
|
+
Requires Node.js 20 or newer.
|
|
13
|
+
|
|
14
|
+
Install the CLI globally from npm:
|
|
6
15
|
|
|
7
16
|
```sh
|
|
8
|
-
npm
|
|
17
|
+
npm i -g inbox-to-md
|
|
9
18
|
```
|
|
10
19
|
|
|
11
|
-
|
|
20
|
+
Configure an IMAP account, then sync it:
|
|
12
21
|
|
|
13
|
-
|
|
22
|
+
```sh
|
|
23
|
+
inbox-to-md auth
|
|
24
|
+
inbox-to-md sync
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
You can also run the latest published version without installing it globally:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
npx inbox-to-md auth
|
|
31
|
+
npx inbox-to-md sync
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Commands
|
|
14
35
|
|
|
15
36
|
```sh
|
|
16
|
-
inbox-to-md auth #
|
|
17
|
-
inbox-to-md
|
|
18
|
-
inbox-to-md
|
|
19
|
-
inbox-to-md
|
|
37
|
+
inbox-to-md auth # add, edit, or delete IMAP accounts and sync paths
|
|
38
|
+
inbox-to-md authcli <action> # manage accounts non-interactively with flags and JSON
|
|
39
|
+
inbox-to-md sync # sync INBOX and Sent mail from this month and last month
|
|
40
|
+
inbox-to-md compact # compact all messages into one Markdown file
|
|
41
|
+
inbox-to-md archive <md dir> # archive the emails represented by files in a directory
|
|
20
42
|
```
|
|
21
43
|
|
|
22
|
-
|
|
44
|
+
Sync from a specific date or overwrite messages that have already been downloaded:
|
|
23
45
|
|
|
24
46
|
```sh
|
|
25
|
-
inbox-to-md sync --since 2026-01-01
|
|
26
|
-
inbox-to-md sync --force-rewrite
|
|
47
|
+
inbox-to-md sync --since 2026-01-01
|
|
48
|
+
inbox-to-md sync --force-rewrite
|
|
27
49
|
```
|
|
28
50
|
|
|
29
|
-
|
|
51
|
+
### Non-interactive authentication
|
|
30
52
|
|
|
31
|
-
|
|
53
|
+
`authcli` manages accounts with flags and returns JSON on stdout. Added and edited accounts are verified over IMAP before they are saved, and passwords are never included in output.
|
|
32
54
|
|
|
33
55
|
```sh
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
56
|
+
inbox-to-md authcli list
|
|
57
|
+
|
|
58
|
+
printf '%s\n' "$IMAP_APP_PASSWORD" | inbox-to-md authcli add \
|
|
59
|
+
--label Gmail \
|
|
60
|
+
--host imap.gmail.com \
|
|
61
|
+
--username you@example.com \
|
|
62
|
+
--password-stdin \
|
|
63
|
+
--sync-path ~/code/obsidian/Emails/Gmail
|
|
64
|
+
|
|
65
|
+
inbox-to-md authcli edit --id <account-id> --sync-path ~/mail/Gmail
|
|
66
|
+
inbox-to-md authcli delete --id <account-id>
|
|
39
67
|
```
|
|
40
68
|
|
|
69
|
+
Port `993` and TLS default to `yes`. A literal `--password <password>` is supported, but `--password-stdin` avoids exposing the secret in process listings or shell history. Run `inbox-to-md authcli --help` for full usage.
|
|
70
|
+
|
|
41
71
|
## License
|
|
42
72
|
|
|
43
73
|
[MIT](LICENSE.md)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ImapAccount } from './config.js';
|
|
2
|
+
export type AccountWithoutId = Omit<ImapAccount, 'id'>;
|
|
3
|
+
export interface AccountValues {
|
|
4
|
+
label: string;
|
|
5
|
+
host: string;
|
|
6
|
+
port: string;
|
|
7
|
+
tls: string;
|
|
8
|
+
username: string;
|
|
9
|
+
password: string;
|
|
10
|
+
syncPath: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function parseAccountValues(values: AccountValues): AccountWithoutId;
|
|
13
|
+
export declare function verifyAccount(account: AccountWithoutId): Promise<void>;
|
|
14
|
+
export declare function parseAndVerifyAccount(values: AccountValues): Promise<AccountWithoutId>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Shared account parsing and IMAP verification for both authentication
|
|
2
|
+
// surfaces. Keep policy here so the interactive TUI and non-interactive CLI
|
|
3
|
+
// cannot disagree about what constitutes a valid, working account.
|
|
4
|
+
import { mkdirSync } from 'fs';
|
|
5
|
+
import { isAbsolute } from 'path';
|
|
6
|
+
import { expandTilde } from './config.js';
|
|
7
|
+
import { closeImapClient, createImapClient, describeImapError } from './imap.js';
|
|
8
|
+
function errorMessage(err) {
|
|
9
|
+
return err instanceof Error ? err.message : String(err);
|
|
10
|
+
}
|
|
11
|
+
export function parseAccountValues(values) {
|
|
12
|
+
const label = values.label.trim();
|
|
13
|
+
if (label === '')
|
|
14
|
+
throw new Error('Label is required');
|
|
15
|
+
const host = values.host.trim();
|
|
16
|
+
if (host === '')
|
|
17
|
+
throw new Error('IMAP host is required');
|
|
18
|
+
if (!/^\d+$/.test(values.port))
|
|
19
|
+
throw new Error('Port must be between 1 and 65535');
|
|
20
|
+
const port = Number(values.port);
|
|
21
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
22
|
+
throw new Error('Port must be between 1 and 65535');
|
|
23
|
+
}
|
|
24
|
+
if (values.tls !== 'yes' && values.tls !== 'no') {
|
|
25
|
+
throw new Error('TLS must be "yes" or "no"');
|
|
26
|
+
}
|
|
27
|
+
const username = values.username.trim();
|
|
28
|
+
if (username === '')
|
|
29
|
+
throw new Error('Username is required');
|
|
30
|
+
if (values.password === '')
|
|
31
|
+
throw new Error('Password is required');
|
|
32
|
+
const syncPath = expandTilde(values.syncPath.trim());
|
|
33
|
+
if (syncPath === '')
|
|
34
|
+
throw new Error('Sync path is required');
|
|
35
|
+
if (!isAbsolute(syncPath))
|
|
36
|
+
throw new Error('Sync path must be absolute (or start with ~)');
|
|
37
|
+
return {
|
|
38
|
+
label,
|
|
39
|
+
host,
|
|
40
|
+
port,
|
|
41
|
+
tls: values.tls === 'yes',
|
|
42
|
+
username,
|
|
43
|
+
password: values.password,
|
|
44
|
+
syncPath,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// Verify before saving. Directory creation remains part of verification so a
|
|
48
|
+
// bad destination fails immediately rather than during a later sync.
|
|
49
|
+
export async function verifyAccount(account) {
|
|
50
|
+
try {
|
|
51
|
+
mkdirSync(account.syncPath, { recursive: true });
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
throw new Error(`Cannot create ${account.syncPath}: ${errorMessage(err)}`);
|
|
55
|
+
}
|
|
56
|
+
const client = createImapClient(account);
|
|
57
|
+
try {
|
|
58
|
+
await client.connect();
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
client.close();
|
|
62
|
+
throw new Error(describeImapError(err, account.host, account.port));
|
|
63
|
+
}
|
|
64
|
+
await closeImapClient(client);
|
|
65
|
+
}
|
|
66
|
+
export async function parseAndVerifyAccount(values) {
|
|
67
|
+
const account = parseAccountValues(values);
|
|
68
|
+
await verifyAccount(account);
|
|
69
|
+
return account;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=account-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-auth.js","sourceRoot":"","sources":["../src/account-auth.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.js
CHANGED
|
@@ -3,11 +3,9 @@
|
|
|
3
3
|
// confirmation, Esc quits. The add/edit form verifies by actually logging in
|
|
4
4
|
// over IMAP before anything is saved.
|
|
5
5
|
import { randomUUID } from 'crypto';
|
|
6
|
-
import { mkdirSync } from 'fs';
|
|
7
|
-
import { isAbsolute } from 'path';
|
|
8
6
|
import { dim, red } from './ansi.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
7
|
+
import { parseAccountValues, parseAndVerifyAccount } from './account-auth.js';
|
|
8
|
+
import { CONFIG_PATH, loadConfig, saveConfig } from './config.js';
|
|
11
9
|
import { enterTui, exitTui, pickFromMenu, runForm } from './tui.js';
|
|
12
10
|
const MENU_FOOTER = '[↑/↓] select · [enter] edit/add · [ctrl+x] delete · [esc] quit';
|
|
13
11
|
const FORM_FOOTER = '[↑/↓] move · [enter] verify & save · [esc] back without saving';
|
|
@@ -19,45 +17,13 @@ function errorMessage(err) {
|
|
|
19
17
|
// success proves host, port, TLS mode, and credentials in one shot.
|
|
20
18
|
// Returns null on success or the error string to show in red.
|
|
21
19
|
async function verifyAccount(values) {
|
|
22
|
-
if (values.label.trim() === '')
|
|
23
|
-
return 'Label is required';
|
|
24
|
-
if (values.host.trim() === '')
|
|
25
|
-
return 'IMAP host is required';
|
|
26
|
-
const port = parseInt(values.port, 10);
|
|
27
|
-
if (!Number.isInteger(port) || port < 1 || port > 65535)
|
|
28
|
-
return 'Port must be between 1 and 65535';
|
|
29
|
-
if (values.username.trim() === '')
|
|
30
|
-
return 'Username is required';
|
|
31
|
-
if (values.password === '')
|
|
32
|
-
return 'Password is required';
|
|
33
|
-
const syncPath = expandTilde(values.syncPath.trim());
|
|
34
|
-
if (syncPath === '')
|
|
35
|
-
return 'Sync path is required';
|
|
36
|
-
if (!isAbsolute(syncPath))
|
|
37
|
-
return 'Sync path must be absolute (or start with ~)';
|
|
38
|
-
// Create the directory now so a bad path fails here, visibly, instead of
|
|
39
|
-
// at sync time.
|
|
40
20
|
try {
|
|
41
|
-
|
|
21
|
+
await parseAndVerifyAccount(values);
|
|
22
|
+
return null;
|
|
42
23
|
}
|
|
43
24
|
catch (err) {
|
|
44
|
-
return
|
|
25
|
+
return errorMessage(err);
|
|
45
26
|
}
|
|
46
|
-
const client = createImapClient({
|
|
47
|
-
host: values.host.trim(),
|
|
48
|
-
port,
|
|
49
|
-
tls: values.tls === 'yes',
|
|
50
|
-
username: values.username.trim(),
|
|
51
|
-
password: values.password,
|
|
52
|
-
});
|
|
53
|
-
try {
|
|
54
|
-
await client.connect();
|
|
55
|
-
}
|
|
56
|
-
catch (err) {
|
|
57
|
-
return describeImapError(err, values.host.trim(), port);
|
|
58
|
-
}
|
|
59
|
-
await closeImapClient(client);
|
|
60
|
-
return null;
|
|
61
27
|
}
|
|
62
28
|
function accountFields(existing) {
|
|
63
29
|
return [
|
|
@@ -85,13 +51,7 @@ async function editAccount(config, index) {
|
|
|
85
51
|
return;
|
|
86
52
|
const account = {
|
|
87
53
|
id: existing?.id ?? randomUUID(),
|
|
88
|
-
|
|
89
|
-
host: result.host.trim(),
|
|
90
|
-
port: parseInt(result.port, 10),
|
|
91
|
-
tls: result.tls === 'yes',
|
|
92
|
-
username: result.username.trim(),
|
|
93
|
-
password: result.password,
|
|
94
|
-
syncPath: expandTilde(result.syncPath.trim()),
|
|
54
|
+
...parseAccountValues(result),
|
|
95
55
|
};
|
|
96
56
|
if (index === null)
|
|
97
57
|
config.accounts.push(account);
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,oEAAoE;AACpE,6EAA6E;AAC7E,sCAAsC;AAEtC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/authcli.js
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
// `inbox-to-md authcli` — non-interactive account management for agents and
|
|
2
|
+
// scripts. Inputs are strict flags, successful results are JSON on stdout,
|
|
3
|
+
// and failures are JSON on stderr with a nonzero exit status. Passwords are
|
|
4
|
+
// accepted but never included in output.
|
|
5
|
+
import { randomUUID } from 'crypto';
|
|
6
|
+
import { readFileSync } from 'fs';
|
|
7
|
+
import { parseAndVerifyAccount } from './account-auth.js';
|
|
8
|
+
import { CONFIG_PATH, loadConfig, saveConfig } from './config.js';
|
|
9
|
+
const VALUE_FLAGS = new Set([
|
|
10
|
+
'id', 'label', 'host', 'port', 'tls', 'username', 'password', 'sync-path',
|
|
11
|
+
]);
|
|
12
|
+
const USAGE = `Usage: inbox-to-md authcli <action> [options]
|
|
13
|
+
|
|
14
|
+
Actions:
|
|
15
|
+
list
|
|
16
|
+
add --label <label> --host <host> [--port <port>] [--tls yes|no]
|
|
17
|
+
--username <username> (--password <password> | --password-stdin)
|
|
18
|
+
--sync-path <path>
|
|
19
|
+
edit --id <id> [--label <label>] [--host <host>] [--port <port>]
|
|
20
|
+
[--tls yes|no] [--username <username>]
|
|
21
|
+
[--password <password> | --password-stdin] [--sync-path <path>]
|
|
22
|
+
delete --id <id>
|
|
23
|
+
|
|
24
|
+
Options:
|
|
25
|
+
--password-stdin read the password from stdin without prompting
|
|
26
|
+
-h, --help show this help
|
|
27
|
+
|
|
28
|
+
Results are JSON on stdout. Errors are JSON on stderr. Passwords are never output.
|
|
29
|
+
Prefer --password-stdin because --password may be visible in process listings and shell history.`;
|
|
30
|
+
function publicAccount(account) {
|
|
31
|
+
const { password: _password, ...safe } = account;
|
|
32
|
+
return safe;
|
|
33
|
+
}
|
|
34
|
+
function output(value) {
|
|
35
|
+
process.stdout.write(JSON.stringify(value) + '\n');
|
|
36
|
+
}
|
|
37
|
+
function fail(message) {
|
|
38
|
+
process.stderr.write(JSON.stringify({ ok: false, error: message }) + '\n');
|
|
39
|
+
process.exitCode = 1;
|
|
40
|
+
throw new HandledError();
|
|
41
|
+
}
|
|
42
|
+
class HandledError extends Error {
|
|
43
|
+
}
|
|
44
|
+
function parseArgs(argv) {
|
|
45
|
+
if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help')
|
|
46
|
+
return { help: true };
|
|
47
|
+
const action = argv[0];
|
|
48
|
+
if (!['list', 'add', 'edit', 'delete'].includes(action)) {
|
|
49
|
+
fail(`Unknown action "${action}". Expected list, add, edit, or delete.`);
|
|
50
|
+
}
|
|
51
|
+
const flags = { passwordStdin: false };
|
|
52
|
+
for (let i = 1; i < argv.length; i++) {
|
|
53
|
+
const arg = argv[i];
|
|
54
|
+
if (arg === '-h' || arg === '--help')
|
|
55
|
+
return { help: true };
|
|
56
|
+
if (arg === '--password-stdin') {
|
|
57
|
+
if (flags.passwordStdin)
|
|
58
|
+
fail('Duplicate flag "--password-stdin".');
|
|
59
|
+
flags.passwordStdin = true;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (!arg.startsWith('--'))
|
|
63
|
+
fail(`Unexpected argument "${arg}".`);
|
|
64
|
+
const equals = arg.indexOf('=');
|
|
65
|
+
const name = arg.slice(2, equals === -1 ? undefined : equals);
|
|
66
|
+
if (!VALUE_FLAGS.has(name))
|
|
67
|
+
fail(`Unknown flag "--${name}".`);
|
|
68
|
+
if (flags[name] !== undefined)
|
|
69
|
+
fail(`Duplicate flag "--${name}".`);
|
|
70
|
+
const value = equals === -1 ? argv[++i] : arg.slice(equals + 1);
|
|
71
|
+
if (value === undefined)
|
|
72
|
+
fail(`--${name} requires a value.`);
|
|
73
|
+
flags[name] = value;
|
|
74
|
+
}
|
|
75
|
+
if (flags.password !== undefined && flags.passwordStdin) {
|
|
76
|
+
fail('Use only one of --password or --password-stdin.');
|
|
77
|
+
}
|
|
78
|
+
return { action: action, flags };
|
|
79
|
+
}
|
|
80
|
+
function rejectFlags(action, flags, allowed) {
|
|
81
|
+
const allowedSet = new Set(allowed);
|
|
82
|
+
const unexpected = [...VALUE_FLAGS].filter((name) => flags[name] !== undefined && !allowedSet.has(name));
|
|
83
|
+
if (flags.passwordStdin && !allowedSet.has('password'))
|
|
84
|
+
unexpected.push('password-stdin');
|
|
85
|
+
if (unexpected.length > 0)
|
|
86
|
+
fail(`${action} does not accept --${unexpected[0]}.`);
|
|
87
|
+
}
|
|
88
|
+
function required(flags, name) {
|
|
89
|
+
const value = flags[name];
|
|
90
|
+
if (value === undefined)
|
|
91
|
+
fail(`--${name} is required.`);
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
function readPassword(flags, requiredForAction) {
|
|
95
|
+
if (flags.password !== undefined)
|
|
96
|
+
return flags.password;
|
|
97
|
+
if (!flags.passwordStdin) {
|
|
98
|
+
if (requiredForAction)
|
|
99
|
+
fail('Use --password or --password-stdin.');
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
if (process.stdin.isTTY)
|
|
103
|
+
fail('--password-stdin requires piped input; it never prompts.');
|
|
104
|
+
return readFileSync(0, 'utf8').replace(/\r?\n$/, '');
|
|
105
|
+
}
|
|
106
|
+
function findAccount(config, id) {
|
|
107
|
+
const index = config.accounts.findIndex((account) => account.id === id);
|
|
108
|
+
if (index === -1)
|
|
109
|
+
fail(`No account found with id "${id}".`);
|
|
110
|
+
return { account: config.accounts[index], index };
|
|
111
|
+
}
|
|
112
|
+
async function add(config, flags) {
|
|
113
|
+
rejectFlags('add', flags, ['label', 'host', 'port', 'tls', 'username', 'password', 'sync-path']);
|
|
114
|
+
const values = {
|
|
115
|
+
label: required(flags, 'label'),
|
|
116
|
+
host: required(flags, 'host'),
|
|
117
|
+
port: flags.port ?? '993',
|
|
118
|
+
tls: flags.tls ?? 'yes',
|
|
119
|
+
username: required(flags, 'username'),
|
|
120
|
+
password: readPassword(flags, true),
|
|
121
|
+
syncPath: required(flags, 'sync-path'),
|
|
122
|
+
};
|
|
123
|
+
const account = { id: randomUUID(), ...await parseAndVerifyAccount(values) };
|
|
124
|
+
config.accounts.push(account);
|
|
125
|
+
saveConfig(config);
|
|
126
|
+
output({ ok: true, action: 'added', account: publicAccount(account), configPath: CONFIG_PATH });
|
|
127
|
+
}
|
|
128
|
+
async function edit(config, flags) {
|
|
129
|
+
rejectFlags('edit', flags, ['id', 'label', 'host', 'port', 'tls', 'username', 'password', 'sync-path']);
|
|
130
|
+
const { account: existing, index } = findAccount(config, required(flags, 'id'));
|
|
131
|
+
const password = readPassword(flags, false);
|
|
132
|
+
const values = {
|
|
133
|
+
label: flags.label ?? existing.label,
|
|
134
|
+
host: flags.host ?? existing.host,
|
|
135
|
+
port: flags.port ?? String(existing.port),
|
|
136
|
+
tls: flags.tls ?? (existing.tls ? 'yes' : 'no'),
|
|
137
|
+
username: flags.username ?? existing.username,
|
|
138
|
+
password: password ?? existing.password,
|
|
139
|
+
syncPath: flags['sync-path'] ?? existing.syncPath,
|
|
140
|
+
};
|
|
141
|
+
const account = { id: existing.id, ...await parseAndVerifyAccount(values) };
|
|
142
|
+
config.accounts[index] = account;
|
|
143
|
+
saveConfig(config);
|
|
144
|
+
output({ ok: true, action: 'edited', account: publicAccount(account), configPath: CONFIG_PATH });
|
|
145
|
+
}
|
|
146
|
+
function remove(config, flags) {
|
|
147
|
+
rejectFlags('delete', flags, ['id']);
|
|
148
|
+
const { account, index } = findAccount(config, required(flags, 'id'));
|
|
149
|
+
config.accounts.splice(index, 1);
|
|
150
|
+
saveConfig(config);
|
|
151
|
+
output({ ok: true, action: 'deleted', account: publicAccount(account), configPath: CONFIG_PATH });
|
|
152
|
+
}
|
|
153
|
+
async function main() {
|
|
154
|
+
const parsed = parseArgs(process.argv.slice(2));
|
|
155
|
+
if ('help' in parsed) {
|
|
156
|
+
console.log(USAGE);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const { action, flags } = parsed;
|
|
160
|
+
const config = loadConfig();
|
|
161
|
+
if (action === 'list') {
|
|
162
|
+
rejectFlags('list', flags, []);
|
|
163
|
+
output({
|
|
164
|
+
ok: true,
|
|
165
|
+
action: 'listed',
|
|
166
|
+
accounts: config.accounts.map(publicAccount),
|
|
167
|
+
configPath: CONFIG_PATH,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
else if (action === 'add') {
|
|
171
|
+
await add(config, flags);
|
|
172
|
+
}
|
|
173
|
+
else if (action === 'edit') {
|
|
174
|
+
await edit(config, flags);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
remove(config, flags);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
main().catch((err) => {
|
|
181
|
+
if (err instanceof HandledError)
|
|
182
|
+
return;
|
|
183
|
+
process.stderr.write(JSON.stringify({
|
|
184
|
+
ok: false,
|
|
185
|
+
error: err instanceof Error ? err.message : String(err),
|
|
186
|
+
}) + '\n');
|
|
187
|
+
process.exitCode = 1;
|
|
188
|
+
});
|
|
189
|
+
//# sourceMappingURL=authcli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authcli.js","sourceRoot":"","sources":["../src/authcli.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// modules the npm scripts use:
|
|
4
4
|
//
|
|
5
5
|
// inbox-to-md auth manage IMAP accounts (interactive TUI)
|
|
6
|
+
// inbox-to-md authcli <action> [...] manage IMAP accounts (flags + JSON)
|
|
6
7
|
// inbox-to-md sync [flags] sync inboxes to markdown (default command)
|
|
7
8
|
// inbox-to-md compact compact synced emails into one digest
|
|
8
9
|
// inbox-to-md archive <md dir> archive the emails behind the .md files
|
|
@@ -14,6 +15,7 @@ import { createRequire } from 'module';
|
|
|
14
15
|
const COMMANDS = {
|
|
15
16
|
sync: './index.js',
|
|
16
17
|
auth: './auth.js',
|
|
18
|
+
authcli: './authcli.js',
|
|
17
19
|
compact: './compact.js',
|
|
18
20
|
archive: './archive.js',
|
|
19
21
|
};
|
|
@@ -21,6 +23,7 @@ const USAGE = `Usage: inbox-to-md <command>
|
|
|
21
23
|
|
|
22
24
|
Commands:
|
|
23
25
|
auth manage IMAP accounts (interactive TUI)
|
|
26
|
+
authcli <action> manage IMAP accounts non-interactively (flags + JSON)
|
|
24
27
|
sync [--since YYYY-MM-DD] [--force-rewrite]
|
|
25
28
|
sync inboxes to markdown (default command)
|
|
26
29
|
compact compact synced emails into one digest per account
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,4EAA4E;AAC5E,+BAA+B;AAC/B,EAAE;AACF,gFAAgF;AAChF,oFAAoF;AACpF,+EAA+E;AAC/E,iFAAiF;AACjF,EAAE;AACF,0EAA0E;AAC1E,6EAA6E;AAC7E,kBAAkB;AAElB,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEvC,MAAM,QAAQ,GAA2B;IACvC,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,WAAW;IACjB,OAAO,EAAE,cAAc;IACvB,OAAO,EAAE,cAAc;CACxB,CAAC;AAEF,MAAM,KAAK,GAAG
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,4EAA4E;AAC5E,+BAA+B;AAC/B,EAAE;AACF,gFAAgF;AAChF,6EAA6E;AAC7E,oFAAoF;AACpF,+EAA+E;AAC/E,iFAAiF;AACjF,EAAE;AACF,0EAA0E;AAC1E,6EAA6E;AAC7E,kBAAkB;AAElB,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEvC,MAAM,QAAQ,GAA2B;IACvC,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,WAAW;IACjB,OAAO,EAAE,cAAc;IACvB,OAAO,EAAE,cAAc;IACvB,OAAO,EAAE,cAAc;CACxB,CAAC;AAEF,MAAM,KAAK,GAAG;;;;;;;;;;;;yCAY2B,CAAC;AAE1C,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAE5B,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACrB,CAAC;KAAM,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;IAC/C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,CAAC;AAClD,CAAC;KAAM,IAAI,GAAG,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,QAAQ,CAAC,EAAE,CAAC;IAC3E,OAAO,CAAC,KAAK,CAAC,oBAAoB,GAAG,QAAQ,KAAK,EAAE,CAAC,CAAC;IACtD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC;KAAM,CAAC;IACN,yEAAyE;IACzE,gCAAgC;IAChC,MAAM,OAAO,GAAG,GAAG,KAAK,SAAS,IAAI,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;IACpE,IAAI,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3D,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AAClC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inbox-to-md",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Sync IMAP inboxes to Markdown files — one file per email, with YAML frontmatter",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"build": "tsc",
|
|
33
33
|
"prepublishOnly": "npm run build",
|
|
34
34
|
"auth": "tsx src/auth.ts",
|
|
35
|
+
"authcli": "tsx src/authcli.ts",
|
|
35
36
|
"dev": "tsx src/index.ts",
|
|
36
37
|
"start": "tsx src/index.ts",
|
|
37
38
|
"archive": "tsx src/archive.ts",
|