latchkey 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.
- package/.nvmrc +1 -0
- package/.pre-commit-config.yaml +22 -0
- package/.prettierignore +4 -0
- package/.prettierrc +7 -0
- package/CLAUDE.md +13 -0
- package/LICENSE +7 -0
- package/README.md +167 -0
- package/dist/scripts/cryptFile.d.ts +21 -0
- package/dist/scripts/cryptFile.d.ts.map +1 -0
- package/dist/scripts/cryptFile.js +106 -0
- package/dist/scripts/cryptFile.js.map +1 -0
- package/dist/scripts/encryptFile.d.ts +21 -0
- package/dist/scripts/encryptFile.d.ts.map +1 -0
- package/dist/scripts/encryptFile.js +101 -0
- package/dist/scripts/encryptFile.js.map +1 -0
- package/dist/scripts/recordBrowserSession.d.ts +18 -0
- package/dist/scripts/recordBrowserSession.d.ts.map +1 -0
- package/dist/scripts/recordBrowserSession.js +213 -0
- package/dist/scripts/recordBrowserSession.js.map +1 -0
- package/dist/src/apiCredentialStore.d.ts +19 -0
- package/dist/src/apiCredentialStore.d.ts.map +1 -0
- package/dist/src/apiCredentialStore.js +65 -0
- package/dist/src/apiCredentialStore.js.map +1 -0
- package/dist/src/apiCredentials.d.ts +134 -0
- package/dist/src/apiCredentials.d.ts.map +1 -0
- package/dist/src/apiCredentials.js +139 -0
- package/dist/src/apiCredentials.js.map +1 -0
- package/dist/src/browserConfig.d.ts +90 -0
- package/dist/src/browserConfig.d.ts.map +1 -0
- package/dist/src/browserConfig.js +259 -0
- package/dist/src/browserConfig.js.map +1 -0
- package/dist/src/browserState.d.ts +8 -0
- package/dist/src/browserState.d.ts.map +1 -0
- package/dist/src/browserState.js +21 -0
- package/dist/src/browserState.js.map +1 -0
- package/dist/src/cli.d.ts +6 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +25 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/cliCommands.d.ts +29 -0
- package/dist/src/cliCommands.d.ts.map +1 -0
- package/dist/src/cliCommands.js +264 -0
- package/dist/src/cliCommands.js.map +1 -0
- package/dist/src/config.d.ts +35 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +96 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/curl.d.ts +29 -0
- package/dist/src/curl.d.ts.map +1 -0
- package/dist/src/curl.js +53 -0
- package/dist/src/curl.js.map +1 -0
- package/dist/src/encryptedStorage.d.ts +39 -0
- package/dist/src/encryptedStorage.d.ts.map +1 -0
- package/dist/src/encryptedStorage.js +128 -0
- package/dist/src/encryptedStorage.js.map +1 -0
- package/dist/src/encryption.d.ts +28 -0
- package/dist/src/encryption.d.ts.map +1 -0
- package/dist/src/encryption.js +86 -0
- package/dist/src/encryption.js.map +1 -0
- package/dist/src/index.d.ts +14 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +17 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/keychain.d.ts +33 -0
- package/dist/src/keychain.d.ts.map +1 -0
- package/dist/src/keychain.js +94 -0
- package/dist/src/keychain.js.map +1 -0
- package/dist/src/playwrightUtils.d.ts +27 -0
- package/dist/src/playwrightUtils.d.ts.map +1 -0
- package/dist/src/playwrightUtils.js +122 -0
- package/dist/src/playwrightUtils.js.map +1 -0
- package/dist/src/registry.d.ts +12 -0
- package/dist/src/registry.d.ts.map +1 -0
- package/dist/src/registry.js +30 -0
- package/dist/src/registry.js.map +1 -0
- package/dist/src/services/base.d.ts +98 -0
- package/dist/src/services/base.d.ts.map +1 -0
- package/dist/src/services/base.js +137 -0
- package/dist/src/services/base.js.map +1 -0
- package/dist/src/services/discord.d.ts +20 -0
- package/dist/src/services/discord.d.ts.map +1 -0
- package/dist/src/services/discord.js +55 -0
- package/dist/src/services/discord.js.map +1 -0
- package/dist/src/services/dropbox.d.ts +23 -0
- package/dist/src/services/dropbox.d.ts.map +1 -0
- package/dist/src/services/dropbox.js +136 -0
- package/dist/src/services/dropbox.js.map +1 -0
- package/dist/src/services/github.d.ts +23 -0
- package/dist/src/services/github.d.ts.map +1 -0
- package/dist/src/services/github.js +110 -0
- package/dist/src/services/github.js.map +1 -0
- package/dist/src/services/index.d.ts +12 -0
- package/dist/src/services/index.d.ts.map +1 -0
- package/dist/src/services/index.js +11 -0
- package/dist/src/services/index.js.map +1 -0
- package/dist/src/services/linear.d.ts +23 -0
- package/dist/src/services/linear.d.ts.map +1 -0
- package/dist/src/services/linear.js +110 -0
- package/dist/src/services/linear.js.map +1 -0
- package/dist/src/services/slack.d.ts +21 -0
- package/dist/src/services/slack.d.ts.map +1 -0
- package/dist/src/services/slack.js +67 -0
- package/dist/src/services/slack.js.map +1 -0
- package/dist/tests/apiCredentialStore.test.d.ts +2 -0
- package/dist/tests/apiCredentialStore.test.d.ts.map +1 -0
- package/dist/tests/apiCredentialStore.test.js +130 -0
- package/dist/tests/apiCredentialStore.test.js.map +1 -0
- package/dist/tests/apiCredentials.test.d.ts +2 -0
- package/dist/tests/apiCredentials.test.d.ts.map +1 -0
- package/dist/tests/apiCredentials.test.js +169 -0
- package/dist/tests/apiCredentials.test.js.map +1 -0
- package/dist/tests/cli.test.d.ts +2 -0
- package/dist/tests/cli.test.d.ts.map +1 -0
- package/dist/tests/cli.test.js +584 -0
- package/dist/tests/cli.test.js.map +1 -0
- package/dist/tests/encryptedStorage.test.d.ts +2 -0
- package/dist/tests/encryptedStorage.test.d.ts.map +1 -0
- package/dist/tests/encryptedStorage.test.js +126 -0
- package/dist/tests/encryptedStorage.test.js.map +1 -0
- package/dist/tests/encryption.test.d.ts +2 -0
- package/dist/tests/encryption.test.d.ts.map +1 -0
- package/dist/tests/encryption.test.js +121 -0
- package/dist/tests/encryption.test.js.map +1 -0
- package/dist/tests/lint.test.d.ts +2 -0
- package/dist/tests/lint.test.d.ts.map +1 -0
- package/dist/tests/lint.test.js +18 -0
- package/dist/tests/lint.test.js.map +1 -0
- package/dist/tests/registry.test.d.ts +2 -0
- package/dist/tests/registry.test.d.ts.map +1 -0
- package/dist/tests/registry.test.js +85 -0
- package/dist/tests/registry.test.js.map +1 -0
- package/dist/tests/servicesAgainstRecordings.test.d.ts +20 -0
- package/dist/tests/servicesAgainstRecordings.test.d.ts.map +1 -0
- package/dist/tests/servicesAgainstRecordings.test.js +157 -0
- package/dist/tests/servicesAgainstRecordings.test.js.map +1 -0
- package/dist/tests/typecheck.test.d.ts +2 -0
- package/dist/tests/typecheck.test.d.ts.map +1 -0
- package/dist/tests/typecheck.test.js +18 -0
- package/dist/tests/typecheck.test.js.map +1 -0
- package/docs/development.md +94 -0
- package/eslint.config.js +30 -0
- package/integrations/SKILL.md +62 -0
- package/package.json +68 -0
- package/scripts/cryptFile.ts +123 -0
- package/scripts/recordBrowserSession.ts +280 -0
- package/scripts/tsconfig.json +10 -0
- package/src/apiCredentialStore.ts +87 -0
- package/src/apiCredentials.ts +180 -0
- package/src/cli.ts +32 -0
- package/src/cliCommands.ts +321 -0
- package/src/config.ts +115 -0
- package/src/curl.ts +78 -0
- package/src/encryptedStorage.ts +161 -0
- package/src/encryption.ts +106 -0
- package/src/index.ts +65 -0
- package/src/keychain.ts +105 -0
- package/src/playwrightUtils.ts +143 -0
- package/src/registry.ts +35 -0
- package/src/services/base.ts +234 -0
- package/src/services/discord.ts +73 -0
- package/src/services/dropbox.ts +173 -0
- package/src/services/github.ts +139 -0
- package/src/services/index.ts +13 -0
- package/src/services/linear.ts +134 -0
- package/src/services/slack.ts +85 -0
- package/tests/apiCredentialStore.test.ts +162 -0
- package/tests/apiCredentials.test.ts +195 -0
- package/tests/cli.test.ts +798 -0
- package/tests/encryptedStorage.test.ts +173 -0
- package/tests/encryption.test.ts +169 -0
- package/tests/lint.test.ts +19 -0
- package/tests/registry.test.ts +103 -0
- package/tests/servicesAgainstRecordings.test.ts +230 -0
- package/tests/typecheck.test.ts +19 -0
- package/tsconfig.json +24 -0
- package/vitest.config.ts +13 -0
package/.nvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
24.13.0
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
default_install_hook_types: [pre-commit]
|
|
2
|
+
|
|
3
|
+
repos:
|
|
4
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
5
|
+
rev: v6.0.0
|
|
6
|
+
hooks:
|
|
7
|
+
- id: trailing-whitespace
|
|
8
|
+
- id: end-of-file-fixer
|
|
9
|
+
- id: check-added-large-files
|
|
10
|
+
exclude: 'uv.lock'
|
|
11
|
+
- id: check-yaml
|
|
12
|
+
- repo: https://github.com/astral-sh/uv-pre-commit
|
|
13
|
+
rev: 0.7.22
|
|
14
|
+
hooks:
|
|
15
|
+
- id: uv-lock
|
|
16
|
+
- repo: local
|
|
17
|
+
hooks:
|
|
18
|
+
- id: ruff
|
|
19
|
+
name: "Python formatter + import sorter (ruff)"
|
|
20
|
+
entry: bash -c 'uv run ruff check --select UP006,UP007,I,F401 --fix --force-exclude --config pyproject.toml "$@" && uv run ruff format --force-exclude --config pyproject.toml "$@"' --
|
|
21
|
+
language: system
|
|
22
|
+
types: [python]
|
package/.prettierignore
ADDED
package/.prettierrc
ADDED
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
For information about the high-level goal and motivations, see README.md.
|
|
2
|
+
|
|
3
|
+
You are a highly intelligent and experienced software creator that codes in a straightforward way, prefers simplicity and avoids overengineering.
|
|
4
|
+
|
|
5
|
+
Typescript style guide:
|
|
6
|
+
|
|
7
|
+
- Use modern Typescript code.
|
|
8
|
+
- Prefer functional, stateless logic as much as possible.
|
|
9
|
+
- Use immutable data structures as much as possible.
|
|
10
|
+
- Do not use abbreviations in variable (class, function, ...) names. It's fine for names to be somewhat verbose.
|
|
11
|
+
- Omit docstrings if they don't add any value beyond what can be obviously inferred from the function signature / class name.
|
|
12
|
+
- Do not throw builtin errors; always replace them with dedicated error subclasses.
|
|
13
|
+
- When done, validate your changes by running `npm lint` and `npm test`.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2026 Imbue (Generally Intelligent, Inc.)
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Latchkey
|
|
2
|
+
|
|
3
|
+
Turn browser logins into usable credentials for local agents.
|
|
4
|
+
|
|
5
|
+
## Quick example
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
latchkey curl -X POST 'https://slack.com/api/conversations.create' \
|
|
9
|
+
-H 'Content-Type: application/json' \
|
|
10
|
+
-d '{"name":"something-urgent"}'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Overview
|
|
14
|
+
|
|
15
|
+
Latchkey is a command-line tool that injects credentials to curl requests to known public APIs.
|
|
16
|
+
|
|
17
|
+
- `latchkey services`
|
|
18
|
+
- Get a list of known and supported third-party services (Slack, Discord, Linear, GitHub, etc.).
|
|
19
|
+
- `latchkey curl <arguments>`
|
|
20
|
+
- Automatically inject credentials to your otherwise standard curl calls to public APIs.
|
|
21
|
+
- (The first time you access a service, a browser pop-up with a login screen appears.)
|
|
22
|
+
|
|
23
|
+
Latchkey is primarily designed for AI agents. By invoking Latchkey, agents can
|
|
24
|
+
prompt the user to authenticate when needed, then continue interacting with
|
|
25
|
+
third-party APIs using standard curl syntax - no custom integrations or embedded
|
|
26
|
+
credentials required.
|
|
27
|
+
|
|
28
|
+
Unlike OAuth-based flows or typical MCP-style integrations, Latchkey does not
|
|
29
|
+
introduce an intermediary between the agent and the service. Requests are made
|
|
30
|
+
directly on the user’s behalf, which enables greater flexibility at the cost of
|
|
31
|
+
formal delegation: agents authenticate as the user.
|
|
32
|
+
|
|
33
|
+
If a service you need isn’t supported yet, contributions are welcome. Adding
|
|
34
|
+
support typically involves writing a small browser automation class that
|
|
35
|
+
extracts API credentials after login. See the [development docs](docs/development.md)
|
|
36
|
+
for details.
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
### Prerequisites
|
|
41
|
+
|
|
42
|
+
- `curl`, `node` and `npm` need to be present on your system in reasonably recent versions.
|
|
43
|
+
- The browser requires a graphical environment.
|
|
44
|
+
|
|
45
|
+
### Steps
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
npm install -g latchkey
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**nvm users**: Global packages are per node version. If you switch versions, reinstall with `npm install -g latchkey`
|
|
52
|
+
|
|
53
|
+
## Integrations
|
|
54
|
+
|
|
55
|
+
Warning: giving AI agents access to your API credentials is potentially
|
|
56
|
+
dangerous. They will be able to perform most of the actions you can. Only do this if
|
|
57
|
+
you're willing to accept the risks.
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
### OpenCode
|
|
61
|
+
```
|
|
62
|
+
mkdir -p ~/.opencode/skills/latchkey
|
|
63
|
+
cp integrations/SKILL.md ~/.opencode/skills/latchkey/SKILL.md
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Claude Code
|
|
67
|
+
```
|
|
68
|
+
mkdir -p ~/.claude/skills/latchkey
|
|
69
|
+
cp integrations/SKILL.md ~/.claude/skills/latchkey/SKILL.md
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Codex
|
|
73
|
+
```
|
|
74
|
+
mkdir -p ~/.codex/skills/latchkey
|
|
75
|
+
cp integrations/SKILL.md ~/.codex/skills/latchkey/SKILL.md
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
## Direct usage
|
|
80
|
+
|
|
81
|
+
Let's revisit the initial example:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
latchkey curl -X POST 'https://slack.com/api/conversations.create' \
|
|
85
|
+
-H 'Content-Type: application/json' \
|
|
86
|
+
-d '{"name":"something-urgent"}'
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Notice that `-H 'Authorization: Bearer ...'` is absent. This is because Latchkey:
|
|
90
|
+
|
|
91
|
+
- Opens the browser with a login screen.
|
|
92
|
+
- After the user logs in, Latchkey extracts the necessary API credentials from the browser session.
|
|
93
|
+
- The browser is closed, the credentials are injected into the arguments, and `curl` is invoked.
|
|
94
|
+
- The credentials are stored so that they can be reused the next time.
|
|
95
|
+
|
|
96
|
+
Otherwise, `latchkey curl` passes your arguments straight
|
|
97
|
+
through to `curl` so you can use the same interface you are used
|
|
98
|
+
to. The return code, stdin and stdout are passed back from curl
|
|
99
|
+
to the caller of `latchkey`.
|
|
100
|
+
|
|
101
|
+
### Remembering API credentials
|
|
102
|
+
|
|
103
|
+
Your API credentials and browser state are stored by default
|
|
104
|
+
under `~/.latchkey`. When a functioning keyring is detected
|
|
105
|
+
(which is the case on most systems), the data is properly
|
|
106
|
+
encrypted.
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
### Inspecting the status of stored credentials
|
|
110
|
+
|
|
111
|
+
Calling `latchkey status <service_name>` will give you
|
|
112
|
+
information about the status of remembered credentials for the
|
|
113
|
+
given service. Possible results are:
|
|
114
|
+
|
|
115
|
+
- `missing`
|
|
116
|
+
- `invalid`
|
|
117
|
+
- `valid`
|
|
118
|
+
|
|
119
|
+
### Clearing credentials
|
|
120
|
+
|
|
121
|
+
Remembered API credentials can expire. The caller of `latchkey
|
|
122
|
+
curl` will typically notice this because the calls will start returning
|
|
123
|
+
HTTP 401 or 403. To verify that, first call `latchkey status`, e.g.:
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
latchkey status discord
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
If the result is `invalid` , meaning the Unauthorized/Forbidden responses are
|
|
130
|
+
caused by invalid or expired credentials rather than insufficient permissions,
|
|
131
|
+
force a new login in the next `latchkey curl` call by clearing the remembered
|
|
132
|
+
API credentials for the service in question, e.g.:
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
latchkey clear discord
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The next `latchkey curl` call will then trigger a new login flow.
|
|
139
|
+
|
|
140
|
+
To clear all stored data (both the credentials store and browser
|
|
141
|
+
state file), run:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
latchkey clear
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Advanced configuration
|
|
148
|
+
|
|
149
|
+
You can set these environment variables to override certain
|
|
150
|
+
defaults:
|
|
151
|
+
|
|
152
|
+
- `LATCHKEY_STORE`: path to the (typically encrypted) file
|
|
153
|
+
containing stored API credentials
|
|
154
|
+
- `LATCHKEY_BROWSER_STATE`: path to the (typically encrypted) file
|
|
155
|
+
containing the state (cookies, local storage, etc.) of
|
|
156
|
+
the browser used for the login popup
|
|
157
|
+
- `LATCHKEY_CURL_PATH`: path to the curl binary
|
|
158
|
+
- `LATCHKEY_KEYRING_SERVICE_NAME`, `LATCHKEY_KEYRING_ACCOUNT_NAME`: identifiers that are used to store the encryption password in your keyring
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
## Disclaimers
|
|
162
|
+
|
|
163
|
+
- Invoking `latchkey curl ...` can sometimes have side effects in the form of
|
|
164
|
+
new API keys being created on your accounts (through browser automation).
|
|
165
|
+
- Using agents for automated access may be prohibited by some services' ToS.
|
|
166
|
+
- We reserve the right to change the license of future releases of Latchkey.
|
|
167
|
+
- Latchkey was not tested on Windows.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
/**
|
|
3
|
+
* CLI tool for encrypting and decrypting latchkey files.
|
|
4
|
+
*
|
|
5
|
+
* This is a developer utility for inspecting and modifying encrypted
|
|
6
|
+
* credential and browser state files.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* npx tsx scripts/cryptFile.ts decrypt <file> # Decrypt file in place
|
|
10
|
+
* npx tsx scripts/cryptFile.ts encrypt <file> # Encrypt file in place
|
|
11
|
+
*
|
|
12
|
+
* The encryption key is sourced from:
|
|
13
|
+
* 1. LATCHKEY_ENCRYPTION_KEY environment variable
|
|
14
|
+
* 2. System keychain
|
|
15
|
+
*
|
|
16
|
+
* Examples:
|
|
17
|
+
* npx tsx scripts/cryptFile.ts decrypt ~/.latchkey/credentials.json
|
|
18
|
+
* npx tsx scripts/cryptFile.ts encrypt ~/.latchkey/credentials.json
|
|
19
|
+
*/
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=cryptFile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cryptFile.d.ts","sourceRoot":"","sources":["../../scripts/cryptFile.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;GAiBG"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
/**
|
|
3
|
+
* CLI tool for encrypting and decrypting latchkey files.
|
|
4
|
+
*
|
|
5
|
+
* This is a developer utility for inspecting and modifying encrypted
|
|
6
|
+
* credential and browser state files.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* npx tsx scripts/cryptFile.ts decrypt <file> # Decrypt file in place
|
|
10
|
+
* npx tsx scripts/cryptFile.ts encrypt <file> # Encrypt file in place
|
|
11
|
+
*
|
|
12
|
+
* The encryption key is sourced from:
|
|
13
|
+
* 1. LATCHKEY_ENCRYPTION_KEY environment variable
|
|
14
|
+
* 2. System keychain
|
|
15
|
+
*
|
|
16
|
+
* Examples:
|
|
17
|
+
* npx tsx scripts/cryptFile.ts decrypt ~/.latchkey/credentials.json
|
|
18
|
+
* npx tsx scripts/cryptFile.ts encrypt ~/.latchkey/credentials.json
|
|
19
|
+
*/
|
|
20
|
+
import { program } from 'commander';
|
|
21
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
22
|
+
import { CONFIG } from '../src/config.js';
|
|
23
|
+
import { EncryptedStorage } from '../src/encryptedStorage.js';
|
|
24
|
+
import { encrypt, generateKey } from '../src/encryption.js';
|
|
25
|
+
import { isKeychainAvailable, retrieveFromKeychain } from '../src/keychain.js';
|
|
26
|
+
const ENCRYPTED_FILE_PREFIX = 'LATCHKEY_ENCRYPTED:';
|
|
27
|
+
function getEncryptionKey() {
|
|
28
|
+
// 1. Check environment variable via Config
|
|
29
|
+
if (CONFIG.encryptionKeyOverride) {
|
|
30
|
+
return CONFIG.encryptionKeyOverride;
|
|
31
|
+
}
|
|
32
|
+
// 2. Check keychain
|
|
33
|
+
if (isKeychainAvailable(CONFIG.serviceName, CONFIG.accountName)) {
|
|
34
|
+
const keychainKey = retrieveFromKeychain(CONFIG.serviceName, CONFIG.accountName);
|
|
35
|
+
if (keychainKey) {
|
|
36
|
+
return keychainKey;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
console.error(`\
|
|
40
|
+
Error: No encryption key available.
|
|
41
|
+
Set LATCHKEY_ENCRYPTION_KEY or ensure the system keychain has a stored key.
|
|
42
|
+
|
|
43
|
+
To generate a new key:
|
|
44
|
+
export LATCHKEY_ENCRYPTION_KEY="${generateKey()}"`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
function decryptCommand(filePath) {
|
|
48
|
+
if (!existsSync(filePath)) {
|
|
49
|
+
console.error(`Error: File not found: ${filePath}`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
const rawContent = readFileSync(filePath, 'utf-8');
|
|
53
|
+
if (!rawContent.startsWith(ENCRYPTED_FILE_PREFIX)) {
|
|
54
|
+
console.error(`Error: File is not encrypted: ${filePath}`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
const storage = new EncryptedStorage({
|
|
58
|
+
serviceName: CONFIG.serviceName,
|
|
59
|
+
accountName: CONFIG.accountName,
|
|
60
|
+
});
|
|
61
|
+
const content = storage.readFile(filePath);
|
|
62
|
+
if (content === null) {
|
|
63
|
+
console.error(`Error: Could not read file: ${filePath}`);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
writeFileSync(filePath, content, { encoding: 'utf-8', mode: 0o600 });
|
|
67
|
+
console.error(`Decrypted: ${filePath}`);
|
|
68
|
+
}
|
|
69
|
+
function encryptCommand(filePath) {
|
|
70
|
+
if (!existsSync(filePath)) {
|
|
71
|
+
console.error(`Error: File not found: ${filePath}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
75
|
+
if (content.startsWith(ENCRYPTED_FILE_PREFIX)) {
|
|
76
|
+
console.error(`Error: File is already encrypted: ${filePath}`);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
const key = getEncryptionKey();
|
|
80
|
+
const encryptedData = encrypt(content, key);
|
|
81
|
+
const dataToWrite = ENCRYPTED_FILE_PREFIX + encryptedData;
|
|
82
|
+
writeFileSync(filePath, dataToWrite, { encoding: 'utf-8', mode: 0o600 });
|
|
83
|
+
console.error(`Encrypted: ${filePath}`);
|
|
84
|
+
}
|
|
85
|
+
program.name('cryptFile').description(`\
|
|
86
|
+
CLI tool for encrypting and decrypting latchkey files.
|
|
87
|
+
|
|
88
|
+
The encryption key is sourced from:
|
|
89
|
+
1. LATCHKEY_ENCRYPTION_KEY environment variable
|
|
90
|
+
2. System keychain`);
|
|
91
|
+
program
|
|
92
|
+
.command('decrypt')
|
|
93
|
+
.description('Decrypt file in place')
|
|
94
|
+
.argument('<file>', 'Path to the encrypted file')
|
|
95
|
+
.action((filePath) => {
|
|
96
|
+
decryptCommand(filePath);
|
|
97
|
+
});
|
|
98
|
+
program
|
|
99
|
+
.command('encrypt')
|
|
100
|
+
.description('Encrypt an unencrypted file in place')
|
|
101
|
+
.argument('<file>', 'Path to the file to encrypt')
|
|
102
|
+
.action((filePath) => {
|
|
103
|
+
encryptCommand(filePath);
|
|
104
|
+
});
|
|
105
|
+
program.parse();
|
|
106
|
+
//# sourceMappingURL=cryptFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cryptFile.js","sourceRoot":"","sources":["../../scripts/cryptFile.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE/E,MAAM,qBAAqB,GAAG,qBAAqB,CAAC;AAEpD,SAAS,gBAAgB;IACvB,2CAA2C;IAC3C,IAAI,MAAM,CAAC,qBAAqB,EAAE,CAAC;QACjC,OAAO,MAAM,CAAC,qBAAqB,CAAC;IACtC,CAAC;IAED,oBAAoB;IACpB,IAAI,mBAAmB,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QAChE,MAAM,WAAW,GAAG,oBAAoB,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QACjF,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,WAAW,CAAC;QACrB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,KAAK,CAAC;;;;;oCAKoB,WAAW,EAAE,GAAG,CAAC,CAAC;IACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,SAAS,cAAc,CAAC,QAAgB;IACtC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,UAAU,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,qBAAqB,CAAC,EAAE,CAAC;QAClD,OAAO,CAAC,KAAK,CAAC,iCAAiC,QAAQ,EAAE,CAAC,CAAC;QAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC;QACnC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,WAAW,EAAE,MAAM,CAAC,WAAW;KAChC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAE3C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,CAAC,KAAK,CAAC,+BAA+B,QAAQ,EAAE,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,OAAO,CAAC,KAAK,CAAC,cAAc,QAAQ,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,cAAc,CAAC,QAAgB;IACtC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChD,IAAI,OAAO,CAAC,UAAU,CAAC,qBAAqB,CAAC,EAAE,CAAC;QAC9C,OAAO,CAAC,KAAK,CAAC,qCAAqC,QAAQ,EAAE,CAAC,CAAC;QAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,GAAG,GAAG,gBAAgB,EAAE,CAAC;IAC/B,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,qBAAqB,GAAG,aAAa,CAAC;IAE1D,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACzE,OAAO,CAAC,KAAK,CAAC,cAAc,QAAQ,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC;;;;;qBAKjB,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,uBAAuB,CAAC;KACpC,QAAQ,CAAC,QAAQ,EAAE,4BAA4B,CAAC;KAChD,MAAM,CAAC,CAAC,QAAgB,EAAE,EAAE;IAC3B,cAAc,CAAC,QAAQ,CAAC,CAAC;AAC3B,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,sCAAsC,CAAC;KACnD,QAAQ,CAAC,QAAQ,EAAE,6BAA6B,CAAC;KACjD,MAAM,CAAC,CAAC,QAAgB,EAAE,EAAE;IAC3B,cAAc,CAAC,QAAQ,CAAC,CAAC;AAC3B,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
/**
|
|
3
|
+
* CLI tool for encrypting and decrypting latchkey files.
|
|
4
|
+
*
|
|
5
|
+
* This is a developer utility for inspecting and modifying encrypted
|
|
6
|
+
* credential and browser state files.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* npx tsx scripts/encryptFile.ts decrypt <file> # Decrypt file to stdout
|
|
10
|
+
* npx tsx scripts/encryptFile.ts encrypt <file> # Encrypt file in place
|
|
11
|
+
*
|
|
12
|
+
* The encryption key is sourced from:
|
|
13
|
+
* 1. LATCHKEY_ENCRYPTION_KEY environment variable
|
|
14
|
+
* 2. System keychain
|
|
15
|
+
*
|
|
16
|
+
* Examples:
|
|
17
|
+
* npx tsx scripts/encryptFile.ts decrypt ~/.latchkey/credentials.json
|
|
18
|
+
* npx tsx scripts/encryptFile.ts encrypt ~/.latchkey/credentials.json
|
|
19
|
+
*/
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=encryptFile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryptFile.d.ts","sourceRoot":"","sources":["../../scripts/encryptFile.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;GAiBG"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
/**
|
|
3
|
+
* CLI tool for encrypting and decrypting latchkey files.
|
|
4
|
+
*
|
|
5
|
+
* This is a developer utility for inspecting and modifying encrypted
|
|
6
|
+
* credential and browser state files.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* npx tsx scripts/encryptFile.ts decrypt <file> # Decrypt file to stdout
|
|
10
|
+
* npx tsx scripts/encryptFile.ts encrypt <file> # Encrypt file in place
|
|
11
|
+
*
|
|
12
|
+
* The encryption key is sourced from:
|
|
13
|
+
* 1. LATCHKEY_ENCRYPTION_KEY environment variable
|
|
14
|
+
* 2. System keychain
|
|
15
|
+
*
|
|
16
|
+
* Examples:
|
|
17
|
+
* npx tsx scripts/encryptFile.ts decrypt ~/.latchkey/credentials.json
|
|
18
|
+
* npx tsx scripts/encryptFile.ts encrypt ~/.latchkey/credentials.json
|
|
19
|
+
*/
|
|
20
|
+
import { program } from 'commander';
|
|
21
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
22
|
+
import { CONFIG } from '../src/config.js';
|
|
23
|
+
import { EncryptedStorage } from '../src/encryptedStorage.js';
|
|
24
|
+
import { encrypt, generateKey } from '../src/encryption.js';
|
|
25
|
+
import { isKeychainAvailable, retrieveFromKeychain } from '../src/keychain.js';
|
|
26
|
+
const ENCRYPTED_FILE_PREFIX = 'LATCHKEY_ENCRYPTED:';
|
|
27
|
+
function getEncryptionKey() {
|
|
28
|
+
// 1. Check environment variable via Config
|
|
29
|
+
if (CONFIG.encryptionKeyOverride) {
|
|
30
|
+
return CONFIG.encryptionKeyOverride;
|
|
31
|
+
}
|
|
32
|
+
// 2. Check keychain
|
|
33
|
+
if (isKeychainAvailable(CONFIG.serviceName, CONFIG.accountName)) {
|
|
34
|
+
const keychainKey = retrieveFromKeychain(CONFIG.serviceName, CONFIG.accountName);
|
|
35
|
+
if (keychainKey) {
|
|
36
|
+
return keychainKey;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
console.error(`\
|
|
40
|
+
Error: No encryption key available.
|
|
41
|
+
Set LATCHKEY_ENCRYPTION_KEY or ensure the system keychain has a stored key.
|
|
42
|
+
|
|
43
|
+
To generate a new key:
|
|
44
|
+
export LATCHKEY_ENCRYPTION_KEY="${generateKey()}"`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
function decryptCommand(filePath) {
|
|
48
|
+
if (!existsSync(filePath)) {
|
|
49
|
+
console.error(`Error: File not found: ${filePath}`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
const storage = new EncryptedStorage({
|
|
53
|
+
serviceName: CONFIG.serviceName,
|
|
54
|
+
accountName: CONFIG.accountName,
|
|
55
|
+
});
|
|
56
|
+
const content = storage.readFile(filePath);
|
|
57
|
+
if (content === null) {
|
|
58
|
+
console.error(`Error: Could not read file: ${filePath}`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
// Output to stdout
|
|
62
|
+
process.stdout.write(content);
|
|
63
|
+
}
|
|
64
|
+
function encryptCommand(filePath) {
|
|
65
|
+
if (!existsSync(filePath)) {
|
|
66
|
+
console.error(`Error: File not found: ${filePath}`);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
70
|
+
if (content.startsWith(ENCRYPTED_FILE_PREFIX)) {
|
|
71
|
+
console.error(`Error: File is already encrypted: ${filePath}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
const key = getEncryptionKey();
|
|
75
|
+
const encryptedData = encrypt(content, key);
|
|
76
|
+
const dataToWrite = ENCRYPTED_FILE_PREFIX + encryptedData;
|
|
77
|
+
writeFileSync(filePath, dataToWrite, { encoding: 'utf-8', mode: 0o600 });
|
|
78
|
+
console.error(`Encrypted: ${filePath}`);
|
|
79
|
+
}
|
|
80
|
+
program.name('encryptFile').description(`\
|
|
81
|
+
CLI tool for encrypting and decrypting latchkey files.
|
|
82
|
+
|
|
83
|
+
The encryption key is sourced from:
|
|
84
|
+
1. LATCHKEY_ENCRYPTION_KEY environment variable
|
|
85
|
+
2. System keychain`);
|
|
86
|
+
program
|
|
87
|
+
.command('decrypt')
|
|
88
|
+
.description('Decrypt file and print to stdout')
|
|
89
|
+
.argument('<file>', 'Path to the encrypted file')
|
|
90
|
+
.action((filePath) => {
|
|
91
|
+
decryptCommand(filePath);
|
|
92
|
+
});
|
|
93
|
+
program
|
|
94
|
+
.command('encrypt')
|
|
95
|
+
.description('Encrypt an unencrypted file in place')
|
|
96
|
+
.argument('<file>', 'Path to the file to encrypt')
|
|
97
|
+
.action((filePath) => {
|
|
98
|
+
encryptCommand(filePath);
|
|
99
|
+
});
|
|
100
|
+
program.parse();
|
|
101
|
+
//# sourceMappingURL=encryptFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryptFile.js","sourceRoot":"","sources":["../../scripts/encryptFile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
/**
|
|
3
|
+
* Record browser requests and responses during a login session.
|
|
4
|
+
*
|
|
5
|
+
* This script opens a browser at a service's login URL and records all HTTP
|
|
6
|
+
* requests and responses (including their headers and timing). When you close the
|
|
7
|
+
* browser, the recording is saved. This is useful for recording login flows that
|
|
8
|
+
* can be replayed later for testing credentials extraction.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* npx tsx scripts/recordBrowserSession.ts <service_name> [recording_name]
|
|
12
|
+
*
|
|
13
|
+
* Examples:
|
|
14
|
+
* npx tsx scripts/recordBrowserSession.ts slack
|
|
15
|
+
* npx tsx scripts/recordBrowserSession.ts discord custom_session.json
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=recordBrowserSession.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recordBrowserSession.d.ts","sourceRoot":"","sources":["../../scripts/recordBrowserSession.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG"}
|