latchkey 0.1.4 → 1.0.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/LICENSE +1 -1
- package/README.md +93 -56
- package/dist/integrations/SKILL.md +77 -0
- package/dist/package.json +67 -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/src/apiCredentialStore.d.ts +1 -0
- package/dist/src/apiCredentialStore.d.ts.map +1 -1
- package/dist/src/apiCredentialStore.js +12 -0
- package/dist/src/apiCredentialStore.js.map +1 -1
- package/dist/src/apiCredentials.d.ts +116 -1
- package/dist/src/apiCredentials.d.ts.map +1 -1
- package/dist/src/apiCredentials.js +119 -1
- package/dist/src/apiCredentials.js.map +1 -1
- 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.js +5 -3
- package/dist/src/cli.js.map +1 -1
- package/dist/src/cliCommands.d.ts.map +1 -1
- package/dist/src/cliCommands.js +218 -81
- package/dist/src/cliCommands.js.map +1 -1
- package/dist/src/config.d.ts +13 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +50 -4
- package/dist/src/config.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/oauthUtils.d.ts +49 -0
- package/dist/src/oauthUtils.d.ts.map +1 -0
- package/dist/src/oauthUtils.js +183 -0
- package/dist/src/oauthUtils.js.map +1 -0
- package/dist/src/playwrightUtils.d.ts +14 -1
- package/dist/src/playwrightUtils.d.ts.map +1 -1
- package/dist/src/playwrightUtils.js +37 -8
- package/dist/src/playwrightUtils.js.map +1 -1
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +20 -4
- package/dist/src/registry.js.map +1 -1
- package/dist/src/services/base.d.ts +43 -15
- package/dist/src/services/base.d.ts.map +1 -1
- package/dist/src/services/base.js +49 -9
- package/dist/src/services/base.js.map +1 -1
- package/dist/src/services/discord.d.ts +4 -3
- package/dist/src/services/discord.d.ts.map +1 -1
- package/dist/src/services/discord.js +6 -22
- package/dist/src/services/discord.js.map +1 -1
- package/dist/src/services/dropbox.d.ts +5 -4
- package/dist/src/services/dropbox.d.ts.map +1 -1
- package/dist/src/services/dropbox.js +10 -27
- package/dist/src/services/dropbox.js.map +1 -1
- package/dist/src/services/github.d.ts +5 -4
- package/dist/src/services/github.d.ts.map +1 -1
- package/dist/src/services/github.js +21 -30
- package/dist/src/services/github.js.map +1 -1
- package/dist/src/services/google.d.ts +34 -0
- package/dist/src/services/google.d.ts.map +1 -0
- package/dist/src/services/google.js +336 -0
- package/dist/src/services/google.js.map +1 -0
- package/dist/src/services/index.d.ts +4 -2
- package/dist/src/services/index.d.ts.map +1 -1
- package/dist/src/services/index.js +4 -1
- package/dist/src/services/index.js.map +1 -1
- package/dist/src/services/linear.d.ts +5 -4
- package/dist/src/services/linear.d.ts.map +1 -1
- package/dist/src/services/linear.js +10 -29
- package/dist/src/services/linear.js.map +1 -1
- package/dist/src/services/mailchimp.d.ts +11 -0
- package/dist/src/services/mailchimp.d.ts.map +1 -0
- package/dist/src/services/mailchimp.js +16 -0
- package/dist/src/services/mailchimp.js.map +1 -0
- package/dist/src/services/notion.d.ts +29 -0
- package/dist/src/services/notion.d.ts.map +1 -0
- package/dist/src/services/notion.js +102 -0
- package/dist/src/services/notion.js.map +1 -0
- package/dist/src/services/slack.d.ts +3 -1
- package/dist/src/services/slack.d.ts.map +1 -1
- package/dist/src/services/slack.js +5 -5
- package/dist/src/services/slack.js.map +1 -1
- package/dist/src/skillMd.d.ts +2 -0
- package/dist/src/skillMd.d.ts.map +1 -0
- package/dist/src/skillMd.js +19 -0
- package/dist/src/skillMd.js.map +1 -0
- package/dist/tests/apiCredentials.test.js +59 -1
- package/dist/tests/apiCredentials.test.js.map +1 -1
- package/dist/tests/cli.test.js +283 -104
- package/dist/tests/cli.test.js.map +1 -1
- package/dist/tests/playwrightDownload.test.js +2 -2
- package/dist/tests/playwrightDownload.test.js.map +1 -1
- package/dist/tests/registry.test.js +28 -3
- package/dist/tests/registry.test.js.map +1 -1
- package/dist/tests/servicesAgainstRecordings.test.js +3 -0
- package/dist/tests/servicesAgainstRecordings.test.js.map +1 -1
- package/package.json +6 -6
package/LICENSE
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright 2026 Imbue
|
|
1
|
+
Copyright 2026 Imbue, Inc.
|
|
2
2
|
|
|
3
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
4
|
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Latchkey
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Inject API credentials into local agent requests.
|
|
4
4
|
|
|
5
5
|
## Quick example
|
|
6
6
|
|
|
@@ -12,75 +12,88 @@ latchkey curl -X POST 'https://slack.com/api/conversations.create' \
|
|
|
12
12
|
|
|
13
13
|
## Overview
|
|
14
14
|
|
|
15
|
-
Latchkey is a command-line tool that injects credentials
|
|
15
|
+
Latchkey is a command-line tool that injects credentials into curl
|
|
16
|
+
requests to known public APIs.
|
|
16
17
|
|
|
17
|
-
- `latchkey services`
|
|
18
|
-
- Get a list of
|
|
18
|
+
- `latchkey services list`
|
|
19
|
+
- Get a list of supported third-party services (Slack, Google Workspace, Linear, GitHub, etc.).
|
|
19
20
|
- `latchkey curl <arguments>`
|
|
20
21
|
- Automatically inject credentials to your otherwise standard curl calls to public APIs.
|
|
21
|
-
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
22
|
+
- Credentials must already exist (see below).
|
|
23
|
+
- `latchkey auth set <service_name> <curl_arguments>`
|
|
24
|
+
- Manually store credentials for a service in the form of arbitrary curl arguments.
|
|
25
|
+
- `latchkey auth browser <service_name>`
|
|
26
|
+
- Open a browser login pop-up window and store the resulting API credentials.
|
|
27
|
+
- Only some services support this option.
|
|
28
|
+
|
|
29
|
+
Latchkey is primarily designed for AI agents. By invoking
|
|
30
|
+
Latchkey, agents can prompt the user to authenticate when needed,
|
|
31
|
+
then continue interacting with third-party APIs using standard
|
|
32
|
+
curl syntax - no custom integrations or embedded credentials
|
|
33
|
+
required.
|
|
34
|
+
|
|
35
|
+
Unlike OAuth-based flows or typical MCP-style integrations,
|
|
36
|
+
Latchkey does not introduce an intermediary between the agent
|
|
37
|
+
and the service. When `browser` is used, requests are made
|
|
38
|
+
directly on the user’s behalf, which enables greater flexibility
|
|
39
|
+
at the cost of formal delegation: agents authenticate as the
|
|
40
|
+
user.
|
|
41
|
+
|
|
42
|
+
If a service you need isn’t supported yet, contributions are welcome!
|
|
43
|
+
See the [development docs](docs/development.md) for details.
|
|
37
44
|
|
|
38
45
|
## Installation
|
|
39
46
|
|
|
40
47
|
### Prerequisites
|
|
41
48
|
|
|
42
49
|
- `curl`, `node` and `npm` need to be present on your system in reasonably recent versions.
|
|
43
|
-
- The browser requires a graphical environment.
|
|
50
|
+
- The `latchkey auth browser` subcommand requires a graphical environment.
|
|
44
51
|
|
|
45
52
|
### Steps
|
|
46
53
|
|
|
47
54
|
```
|
|
48
55
|
npm install -g latchkey
|
|
56
|
+
|
|
57
|
+
# Optionally, if you intend to use `latchkey auth browser`:
|
|
49
58
|
latchkey ensure-browser
|
|
50
59
|
```
|
|
51
60
|
|
|
52
|
-
The `ensure-browser` command discovers and configures a browser
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
The `ensure-browser` command discovers and configures a browser
|
|
62
|
+
for Latchkey to use. It searches for Chrome, Chromium, or Edge
|
|
63
|
+
on your system. If none is found, it downloads Chromium via
|
|
64
|
+
Playwright.
|
|
55
65
|
|
|
56
66
|
## Integrations
|
|
57
67
|
|
|
58
|
-
Warning: giving AI agents access to your API credentials is
|
|
59
|
-
dangerous
|
|
60
|
-
|
|
68
|
+
Warning: giving AI agents access to your API credentials is
|
|
69
|
+
potentially dangerous, especially when using the `auth browser`
|
|
70
|
+
feature. They will be able to perform most of the actions you
|
|
71
|
+
can. Only do this if you're willing to accept the risks.
|
|
61
72
|
|
|
62
73
|
|
|
63
74
|
### OpenCode
|
|
64
75
|
```
|
|
65
76
|
mkdir -p ~/.opencode/skills/latchkey
|
|
66
|
-
|
|
77
|
+
latchkey skill-md > ~/.opencode/skills/latchkey/SKILL.md
|
|
67
78
|
```
|
|
68
79
|
|
|
69
80
|
### Claude Code
|
|
70
81
|
```
|
|
71
82
|
mkdir -p ~/.claude/skills/latchkey
|
|
72
|
-
|
|
83
|
+
latchkey skill-md > ~/.claude/skills/latchkey/SKILL.md
|
|
73
84
|
```
|
|
74
85
|
|
|
75
86
|
### Codex
|
|
76
87
|
```
|
|
77
88
|
mkdir -p ~/.codex/skills/latchkey
|
|
78
|
-
|
|
89
|
+
latchkey skill-md > ~/.codex/skills/latchkey/SKILL.md
|
|
79
90
|
```
|
|
80
91
|
|
|
81
92
|
### Passepartout
|
|
82
93
|
|
|
83
|
-
Check out our [Passepartout demo app](https://github.com/imbue-ai/passepartout)
|
|
94
|
+
Check out our [Passepartout demo app](https://github.com/imbue-ai/passepartout)
|
|
95
|
+
for an idea of how to build AI assistants for non-technical
|
|
96
|
+
users on top of Latchkey.
|
|
84
97
|
|
|
85
98
|
|
|
86
99
|
## Demo
|
|
@@ -98,17 +111,28 @@ latchkey curl -X POST 'https://slack.com/api/conversations.create' \
|
|
|
98
111
|
-d '{"name":"something-urgent"}'
|
|
99
112
|
```
|
|
100
113
|
|
|
101
|
-
Notice that `-H 'Authorization: Bearer ...'` is absent. This is
|
|
114
|
+
Notice that `-H 'Authorization: Bearer ...'` is absent. This is
|
|
115
|
+
because Latchkey injects stored credentials automatically. To
|
|
116
|
+
set up credentials for a service (Slack in this example), run:
|
|
102
117
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
118
|
+
```
|
|
119
|
+
latchkey auth browser slack
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
This opens the browser with a login screen. After you log in, Latchkey extracts
|
|
123
|
+
the necessary API credentials from the browser session, closes the browser, and
|
|
124
|
+
stores the credentials so that they can be reused.
|
|
125
|
+
|
|
126
|
+
Alternatively, you can provide credentials manually:
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
latchkey auth set slack -H "Authorization: Bearer xoxb-your-token"
|
|
130
|
+
```
|
|
107
131
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
132
|
+
`latchkey curl` passes your arguments straight through to `curl`
|
|
133
|
+
so you can use the same interface you are used to. The return
|
|
134
|
+
code, stdout and stderr are passed back from curl to the caller
|
|
135
|
+
of `latchkey`.
|
|
112
136
|
|
|
113
137
|
### Remembering API credentials
|
|
114
138
|
|
|
@@ -120,9 +144,9 @@ encrypted.
|
|
|
120
144
|
|
|
121
145
|
### Inspecting the status of stored credentials
|
|
122
146
|
|
|
123
|
-
Calling `latchkey
|
|
124
|
-
|
|
125
|
-
|
|
147
|
+
Calling `latchkey services info <service_name>` will show information
|
|
148
|
+
about the service, including the credentials status. The
|
|
149
|
+
credentials status line will show one of:
|
|
126
150
|
|
|
127
151
|
- `missing`
|
|
128
152
|
- `invalid`
|
|
@@ -132,30 +156,42 @@ given service. Possible results are:
|
|
|
132
156
|
|
|
133
157
|
Remembered API credentials can expire. The caller of `latchkey
|
|
134
158
|
curl` will typically notice this because the calls will start returning
|
|
135
|
-
HTTP 401 or 403. To verify that, first call `latchkey
|
|
159
|
+
HTTP 401 or 403. To verify that, first call `latchkey services info`, e.g.:
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
latchkey services info discord
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
If the credentials status is `invalid`, it means the Unauthorized/Forbidden
|
|
166
|
+
responses are caused by invalid or expired credentials rather than insufficient
|
|
167
|
+
permissions. In that case, log in again:
|
|
136
168
|
|
|
137
169
|
```
|
|
138
|
-
latchkey
|
|
170
|
+
latchkey auth browser discord
|
|
139
171
|
```
|
|
140
172
|
|
|
141
|
-
|
|
142
|
-
caused by invalid or expired credentials rather than insufficient permissions,
|
|
143
|
-
force a new login in the next `latchkey curl` call by clearing the remembered
|
|
144
|
-
API credentials for the service in question, e.g.:
|
|
173
|
+
Or alternatively:
|
|
145
174
|
|
|
146
175
|
```
|
|
147
|
-
latchkey
|
|
176
|
+
latchkey auth set discord -H "Authorization: ..."
|
|
148
177
|
```
|
|
149
178
|
|
|
150
|
-
The next `latchkey curl` call will then trigger a new login flow.
|
|
151
179
|
|
|
152
|
-
|
|
153
|
-
|
|
180
|
+
### Clearing credentials and logins
|
|
181
|
+
|
|
182
|
+
In case you want to remove stored API credentials, use the `auth clear` subcommand.
|
|
154
183
|
|
|
155
184
|
```
|
|
156
|
-
latchkey clear
|
|
185
|
+
latchkey auth clear discord
|
|
157
186
|
```
|
|
158
187
|
|
|
188
|
+
To clear all stored data (both the credential store and browser state file), run:
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
latchkey auth clear
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
|
|
159
195
|
### Advanced configuration
|
|
160
196
|
|
|
161
197
|
You can set these environment variables to override certain
|
|
@@ -166,17 +202,18 @@ containing stored API credentials
|
|
|
166
202
|
- `LATCHKEY_BROWSER_STATE`: path to the (typically encrypted) file
|
|
167
203
|
containing the state (cookies, local storage, etc.) of
|
|
168
204
|
the browser used for the login popup
|
|
169
|
-
- `
|
|
205
|
+
- `LATCHKEY_CURL`: path to the curl binary
|
|
170
206
|
- `LATCHKEY_CONFIG`: path to the configuration file
|
|
171
207
|
(defaults to `~/.latchkey/config.json`)
|
|
172
208
|
- `LATCHKEY_KEYRING_SERVICE_NAME`, `LATCHKEY_KEYRING_ACCOUNT_NAME`: identifiers that are used to store the encryption password in your keyring
|
|
209
|
+
- `LATCHKEY_DISABLE_BROWSER`: when set (to any non-empty value), disables the browser login flow; commands that would trigger a browser login (`auth browser`, `auth browser-prepare`) will fail with an error instead
|
|
173
210
|
|
|
174
211
|
|
|
175
212
|
## Disclaimers
|
|
176
213
|
|
|
177
214
|
- This is still a work in progress.
|
|
178
215
|
- Latchkey has been created with the help of AI-assisted coding tools with careful human curation.
|
|
179
|
-
- Invoking `latchkey
|
|
216
|
+
- Invoking `latchkey auth browser ...` can sometimes have side effects in the form of
|
|
180
217
|
new API keys being created in your accounts (through browser automation).
|
|
181
218
|
- Using agents for automated access may be prohibited by some services' ToS.
|
|
182
219
|
- We reserve the right to change the license of future releases of Latchkey.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: latchkey
|
|
3
|
+
description: Interact with third-party services (Slack, Google Workspace, Dropbox, GitHub, Linear...) on the user's behalf using their public APIs.
|
|
4
|
+
compatibility: Requires node.js, curl and latchkey (npm install -g latchkey). A desktop/GUI environment is required for the browser functionality.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Latchkey
|
|
8
|
+
|
|
9
|
+
## Instructions
|
|
10
|
+
|
|
11
|
+
Latchkey is a CLI tool that automatically injects credentials into curl commands for supported public APIs. Credentials (mostly API tokens) can be either manually managed or, for some services, Latchkey can open a browser login pop-up window and extract API credentials from the session.
|
|
12
|
+
|
|
13
|
+
Use this skill when the user asks you to work with third-party services like Slack, Discord, Dropbox, GitHub, Linear and others on their behalf.
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
|
|
17
|
+
1. **Use `latchkey curl`** instead of regular `curl` for supported services.
|
|
18
|
+
2. **Pass through all regular curl arguments** - latchkey is a transparent wrapper.
|
|
19
|
+
3. **Use `latchkey services list`** to get a list of supported services.
|
|
20
|
+
4. **Use `latchkey services info <service_name>`** to get information about a specific service (auth options, credentials status, API docs links, special requirements, etc.).
|
|
21
|
+
5. **If necessary, get or renew credentials first.** Run `latchkey auth browser <service_name>` to open a browser login pop-up window if supported.
|
|
22
|
+
6. **Look for the newest documentation of the desired public API online.** If using the `browser` auth command, avoid bot-only endpoints.
|
|
23
|
+
7. **Do not initiate a new login if the credentials status is `valid`** - the user might just not have the necessary permissions for the action you're trying to do.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
### Make an authenticated curl request
|
|
29
|
+
```bash
|
|
30
|
+
latchkey curl [curl arguments]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Creating a Slack channel
|
|
34
|
+
```bash
|
|
35
|
+
latchkey curl -X POST 'https://slack.com/api/conversations.create' \
|
|
36
|
+
-H 'Content-Type: application/json' \
|
|
37
|
+
-d '{"name":"my-channel"}'
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
(Notice that `-H 'Authorization: Bearer` is not present in the invocation.)
|
|
41
|
+
|
|
42
|
+
### Getting Discord user info
|
|
43
|
+
```bash
|
|
44
|
+
latchkey curl 'https://discord.com/api/v10/users/@me'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Detect expired credentials and force a new login to Discord
|
|
48
|
+
```bash
|
|
49
|
+
latchkey services info discord # Check the "credentialStatus" field - shows "invalid"
|
|
50
|
+
latchkey auth browser discord
|
|
51
|
+
latchkey curl 'https://discord.com/api/v10/users/@me'
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Only do this when you notice that your previous call ended up not being authenticated (HTTP 401 or 403).
|
|
55
|
+
|
|
56
|
+
### List available services
|
|
57
|
+
```bash
|
|
58
|
+
latchkey services list
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Lists all services that latchkey knows about.
|
|
62
|
+
|
|
63
|
+
### Get service-specific info
|
|
64
|
+
```bash
|
|
65
|
+
latchkey services info slack
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Returns auth options, credentials status, and developer notes
|
|
69
|
+
about the service. If `browser` is not present in the
|
|
70
|
+
`authOptions` field, the service requires the user to directly
|
|
71
|
+
set API credentials via `latchkey auth set` before making
|
|
72
|
+
requests.
|
|
73
|
+
|
|
74
|
+
## Notes
|
|
75
|
+
|
|
76
|
+
- All curl arguments are passed through unchanged
|
|
77
|
+
- Return code, stdout and stderr are passed back from curl
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "latchkey",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A CLI tool that injects API credentials into curl requests for known third-party services",
|
|
5
|
+
"author": "Imbue <hynek@imbue.com>",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/imbue-ai/latchkey.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/imbue-ai/latchkey#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/imbue-ai/latchkey/issues"
|
|
13
|
+
},
|
|
14
|
+
"type": "module",
|
|
15
|
+
"main": "dist/src/index.js",
|
|
16
|
+
"types": "dist/src/index.d.ts",
|
|
17
|
+
"bin": {
|
|
18
|
+
"latchkey": "./dist/src/cli.js"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"prepublishOnly": "npm run build",
|
|
27
|
+
"build": "tsc && node -e \"require('fs').cpSync('integrations', 'dist/integrations', {recursive:true})\" ",
|
|
28
|
+
"dev": "tsc --watch",
|
|
29
|
+
"lint": "eslint src tests scripts",
|
|
30
|
+
"lint:fix": "eslint src tests scripts --fix",
|
|
31
|
+
"format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\" \"scripts/**/*.ts\"",
|
|
32
|
+
"format:check": "prettier --check \"src/**/*.ts\" \"tests/**/*.ts\" \"scripts/**/*.ts\"",
|
|
33
|
+
"typecheck": "tsc --noEmit",
|
|
34
|
+
"test": "vitest run",
|
|
35
|
+
"test:watch": "vitest",
|
|
36
|
+
"start": "node dist/cli.js",
|
|
37
|
+
"bun-compile": "bun build ./src/cli.ts --compile --external chromium-bidi --external electron --outfile latchkey"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"cli",
|
|
41
|
+
"curl",
|
|
42
|
+
"api",
|
|
43
|
+
"credentials",
|
|
44
|
+
"authentication",
|
|
45
|
+
"agents",
|
|
46
|
+
"imbue"
|
|
47
|
+
],
|
|
48
|
+
"license": "MIT",
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=20"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@napi-rs/keyring": "^1.2.0",
|
|
54
|
+
"commander": "^12.0.0",
|
|
55
|
+
"playwright": "^1.58.2",
|
|
56
|
+
"zod": "^3.22.0"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@eslint/js": "^9.39.2",
|
|
60
|
+
"@types/node": "^20.0.0",
|
|
61
|
+
"eslint": "^9.39.2",
|
|
62
|
+
"prettier": "^3.8.1",
|
|
63
|
+
"typescript": "^5.3.0",
|
|
64
|
+
"typescript-eslint": "^8.53.1",
|
|
65
|
+
"vitest": "^2.0.0"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -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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"}
|
|
@@ -14,6 +14,7 @@ export declare class ApiCredentialStore {
|
|
|
14
14
|
private saveStoreData;
|
|
15
15
|
get(serviceName: string): ApiCredentials | null;
|
|
16
16
|
save(serviceName: string, apiCredentials: ApiCredentials): void;
|
|
17
|
+
getAll(): ReadonlyMap<string, ApiCredentials>;
|
|
17
18
|
delete(serviceName: string): boolean;
|
|
18
19
|
}
|
|
19
20
|
//# sourceMappingURL=apiCredentialStore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiCredentialStore.d.ts","sourceRoot":"","sources":["../../src/apiCredentialStore.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,cAAc,EAIf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAID,qBAAa,kBAAkB;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;gBAExC,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,gBAAgB;IAK5D,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,aAAa;IAUrB,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAiB/C,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,cAAc,GAAG,IAAI;IAM/D,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;CASrC"}
|
|
1
|
+
{"version":3,"file":"apiCredentialStore.d.ts","sourceRoot":"","sources":["../../src/apiCredentialStore.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,cAAc,EAIf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAID,qBAAa,kBAAkB;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;gBAExC,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,gBAAgB;IAK5D,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,aAAa;IAUrB,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAiB/C,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,cAAc,GAAG,IAAI;IAM/D,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC;IAe7C,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;CASrC"}
|
|
@@ -52,6 +52,18 @@ export class ApiCredentialStore {
|
|
|
52
52
|
data[serviceName] = serializeCredentials(apiCredentials);
|
|
53
53
|
this.saveStoreData(data);
|
|
54
54
|
}
|
|
55
|
+
getAll() {
|
|
56
|
+
const data = this.loadStoreData();
|
|
57
|
+
const result = new Map();
|
|
58
|
+
for (const [serviceName, credentialData] of Object.entries(data)) {
|
|
59
|
+
const parseResult = ApiCredentialsSchema.safeParse(credentialData);
|
|
60
|
+
if (!parseResult.success) {
|
|
61
|
+
throw new ApiCredentialStoreError(`Invalid credential data for service ${serviceName}: ${parseResult.error.message}`);
|
|
62
|
+
}
|
|
63
|
+
result.set(serviceName, deserializeCredentials(parseResult.data));
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
55
67
|
delete(serviceName) {
|
|
56
68
|
const data = this.loadStoreData();
|
|
57
69
|
if (!(serviceName in data)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiCredentialStore.js","sourceRoot":"","sources":["../../src/apiCredentialStore.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"apiCredentialStore.js","sourceRoot":"","sources":["../../src/apiCredentialStore.ts"],"names":[],"mappings":"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"}
|