@loredotlink/cli 0.1.180
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 +111 -0
- package/README.md +308 -0
- package/dist/index.js +700 -0
- package/package.json +62 -0
- package/scripts/nodeVersionGuard.mjs +27 -0
- package/scripts/runPostinstallCommand.mjs +79 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
Portions of this software are licensed as follows:
|
|
2
|
+
|
|
3
|
+
* All content that resides under the "ee/" directory of this repository, if that directory exists, is licensed under the license defined in "ee/LICENSE".
|
|
4
|
+
* All third party components incorporated into the Tanagram Software are licensed under the original license provided by the owner of the applicable component.
|
|
5
|
+
* Content outside of the above mentioned directories or restrictions above is available under the "FSL-1.1-ALv2" license as defined below.
|
|
6
|
+
|
|
7
|
+
# Functional Source License, Version 1.1, ALv2 Future License
|
|
8
|
+
|
|
9
|
+
## Abbreviation
|
|
10
|
+
|
|
11
|
+
FSL-1.1-ALv2
|
|
12
|
+
|
|
13
|
+
## Notice
|
|
14
|
+
|
|
15
|
+
Copyright 2026 Tanagram, Inc.
|
|
16
|
+
|
|
17
|
+
## Terms and Conditions
|
|
18
|
+
|
|
19
|
+
### Licensor ("We")
|
|
20
|
+
|
|
21
|
+
The party offering the Software under these Terms and Conditions.
|
|
22
|
+
|
|
23
|
+
### The Software
|
|
24
|
+
|
|
25
|
+
The "Software" is each version of the software that we make available under
|
|
26
|
+
these Terms and Conditions, as indicated by our inclusion of these Terms and
|
|
27
|
+
Conditions with the Software.
|
|
28
|
+
|
|
29
|
+
### License Grant
|
|
30
|
+
|
|
31
|
+
Subject to your compliance with this License Grant and the Patents,
|
|
32
|
+
Redistribution and Trademark clauses below, we hereby grant you the right to
|
|
33
|
+
use, copy, modify, create derivative works, publicly perform, publicly display
|
|
34
|
+
and redistribute the Software for any Permitted Purpose identified below.
|
|
35
|
+
|
|
36
|
+
### Permitted Purpose
|
|
37
|
+
|
|
38
|
+
A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
|
|
39
|
+
means making the Software available to others in a commercial product or
|
|
40
|
+
service that:
|
|
41
|
+
|
|
42
|
+
1. substitutes for the Software;
|
|
43
|
+
|
|
44
|
+
2. substitutes for any other product or service we offer using the Software
|
|
45
|
+
that exists as of the date we make the Software available; or
|
|
46
|
+
|
|
47
|
+
3. offers the same or substantially similar functionality as the Software.
|
|
48
|
+
|
|
49
|
+
Permitted Purposes specifically include using the Software:
|
|
50
|
+
|
|
51
|
+
1. for your internal use and access;
|
|
52
|
+
|
|
53
|
+
2. for non-commercial education;
|
|
54
|
+
|
|
55
|
+
3. for non-commercial research; and
|
|
56
|
+
|
|
57
|
+
4. in connection with professional services that you provide to a licensee
|
|
58
|
+
using the Software in accordance with these Terms and Conditions.
|
|
59
|
+
|
|
60
|
+
### Patents
|
|
61
|
+
|
|
62
|
+
To the extent your use for a Permitted Purpose would necessarily infringe our
|
|
63
|
+
patents, the license grant above includes a license under our patents. If you
|
|
64
|
+
make a claim against any party that the Software infringes or contributes to
|
|
65
|
+
the infringement of any patent, then your patent license to the Software ends
|
|
66
|
+
immediately.
|
|
67
|
+
|
|
68
|
+
### Redistribution
|
|
69
|
+
|
|
70
|
+
The Terms and Conditions apply to all copies, modifications and derivatives of
|
|
71
|
+
the Software.
|
|
72
|
+
|
|
73
|
+
If you redistribute any copies, modifications or derivatives of the Software,
|
|
74
|
+
you must include a copy of or a link to these Terms and Conditions and not
|
|
75
|
+
remove any copyright notices provided in or with the Software.
|
|
76
|
+
|
|
77
|
+
### Disclaimer
|
|
78
|
+
|
|
79
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
|
|
80
|
+
IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
|
|
81
|
+
PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
|
|
82
|
+
|
|
83
|
+
IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
|
|
84
|
+
SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
|
|
85
|
+
EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
|
|
86
|
+
|
|
87
|
+
### Trademarks
|
|
88
|
+
|
|
89
|
+
Except for displaying the License Details and identifying us as the origin of
|
|
90
|
+
the Software, you have no right under these Terms and Conditions to use our
|
|
91
|
+
trademarks, trade names, service marks or product names.
|
|
92
|
+
|
|
93
|
+
## Grant of Future License
|
|
94
|
+
|
|
95
|
+
We hereby irrevocably grant you an additional license to use the Software under
|
|
96
|
+
the Apache License, Version 2.0 that is effective on the second anniversary of
|
|
97
|
+
the date we make the Software available. On or after that date, you may use the
|
|
98
|
+
Software under the Apache License, Version 2.0, in which case the following
|
|
99
|
+
will apply:
|
|
100
|
+
|
|
101
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
102
|
+
this file except in compliance with the License.
|
|
103
|
+
|
|
104
|
+
You may obtain a copy of the License at
|
|
105
|
+
|
|
106
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
107
|
+
|
|
108
|
+
Unless required by applicable law or agreed to in writing, software distributed
|
|
109
|
+
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
110
|
+
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
111
|
+
specific language governing permissions and limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# Lore
|
|
2
|
+
|
|
3
|
+
Lore captures your Claude Code, Codex, and Cowork sessions and turns them
|
|
4
|
+
into something your team can search, discuss, and build on.
|
|
5
|
+
|
|
6
|
+
Your AI coding sessions run on your machine. The Lore CLI watches for new
|
|
7
|
+
ones and uploads them to your workspace automatically, so there is no
|
|
8
|
+
copy-paste, no screenshots, no "save this thread" button to remember.
|
|
9
|
+
|
|
10
|
+
## Get started
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
npm install -g @loredotlink/cli
|
|
14
|
+
lore
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`lore` opens a dashboard in your terminal. Sign in there once and, on
|
|
18
|
+
macOS, background uploads start immediately. On Linux, run `lore configure`
|
|
19
|
+
to pick which directories upload.
|
|
20
|
+
|
|
21
|
+
That's it. Keep coding. New sessions show up in your workspace automatically.
|
|
22
|
+
|
|
23
|
+
## How privacy works
|
|
24
|
+
|
|
25
|
+
**Private by default.** Every session starts visible only to you. You
|
|
26
|
+
choose per session whether to share it with your workspace or make it
|
|
27
|
+
public. Workspace admins cannot override that choice.
|
|
28
|
+
|
|
29
|
+
**You control what uploads.** Lore only uploads sessions from directories
|
|
30
|
+
you allowlist. The first-run wizard pre-checks your three most recent
|
|
31
|
+
projects; nothing outside your allowlist is ever sent. Re-run the picker
|
|
32
|
+
any time with `lore configure`, or edit the list directly:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
lore listen list # what's currently allowlisted
|
|
36
|
+
lore listen create ~/code/project # start uploading from here
|
|
37
|
+
lore listen delete ~/code/project # stop
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**What a session contains.** Your prompts, the assistant's responses,
|
|
41
|
+
tool calls, file edits, and diffs, plus metadata like timestamps, model,
|
|
42
|
+
and the repo it ran in. Diffs include the changed lines of the files you
|
|
43
|
+
edited. Lore does not collect environment variables, secrets, or API keys.
|
|
44
|
+
|
|
45
|
+
**Stop anytime.** `lore disable` halts background uploads. `lore logout`
|
|
46
|
+
removes your stored credentials. You can delete any session, or your whole
|
|
47
|
+
account, from the web app.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Reference: upload filters
|
|
52
|
+
|
|
53
|
+
The Lore background agent evaluates `~/.lore/upload_filters.json`
|
|
54
|
+
(`~/.lore-dev/` in dev) before auto-uploading Claude Code sessions.
|
|
55
|
+
Missing config or an empty `include` allowlist means upload nothing. The `cwd` and `repo`
|
|
56
|
+
allowlists are a union: a session is location-allowed if it matches a
|
|
57
|
+
`cwd` rule OR a `repo` rule (so a non-git directory uploads via its `cwd`
|
|
58
|
+
even when `repo` rules also exist). When set, `include.skills` further
|
|
59
|
+
narrows that set (ANDed). Values within a dimension are ORed, and
|
|
60
|
+
`exclude` rules override includes.
|
|
61
|
+
|
|
62
|
+
The explicit commands (`lore export`, `lore share-codex`,
|
|
63
|
+
`lore share-cowork`) are user-initiated and upload the requested session
|
|
64
|
+
directly.
|
|
65
|
+
|
|
66
|
+
Adding repos and directories through the TUI is a convenience for writing
|
|
67
|
+
`repo` and `cwd` include filters. The post-login wizard shows your
|
|
68
|
+
most-recent Claude Code projects with the top three pre-checked: a project
|
|
69
|
+
inside a git repo is offered as its `origin` remote, and a non-repo
|
|
70
|
+
directory is offered by its path. Pressing Enter accepts them. `lore configure` re-enters that same interactive flow any time
|
|
71
|
+
(it's also one of the quick actions on the `lore` dashboard). For
|
|
72
|
+
scripted/non-interactive edits, use `lore listen` for directory filters;
|
|
73
|
+
`lore listen list` prints the effective repo and cwd upload locations:
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
lore listen create ~/code/projectA # watch ~/code/projectA
|
|
77
|
+
lore listen list # effective repo/cwd locations
|
|
78
|
+
lore listen list --json # for scripts
|
|
79
|
+
lore listen delete ~/code/projectA # stop uploading from
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`cwd` matching uses path-separator-aware **prefix-tree** semantics, so adding
|
|
83
|
+
`~/code` covers `~/code/projectA`, `~/code/projectA/src`, etc., but
|
|
84
|
+
deliberately does **not** cover `~/code-other`. The most-specific
|
|
85
|
+
matching entry wins, so you can have a broad personal `~/` allow plus a
|
|
86
|
+
narrower `~/work` override that routes to a different org.
|
|
87
|
+
|
|
88
|
+
If a `cwd` include points at your entire home directory, `lore listen list`
|
|
89
|
+
prints a warning and suggests replacing it with narrower project paths. Lore
|
|
90
|
+
does not rewrite existing allowlists automatically.
|
|
91
|
+
|
|
92
|
+
## Interactive TUI
|
|
93
|
+
|
|
94
|
+
Running `lore` with no subcommand drops you into an interactive Ink
|
|
95
|
+
dashboard when stdin and stdout are TTYs:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
┌── lore — matt@tanagram.ai · tanagram ─────────────────── v0.1.50 ──┐
|
|
99
|
+
│ │
|
|
100
|
+
│ ╭─ Daemon ──────────────────╮ ╭─ Workspace ─────────────────────╮ │
|
|
101
|
+
│ │ ● Status running │ │ ● User matt@tanagram.ai │ │
|
|
102
|
+
│ │ ● Enabled yes │ │ ● Display Matt │ │
|
|
103
|
+
│ │ ● Running yes │ │ ● Org tanagram │ │
|
|
104
|
+
│ │ ● Heartbeat 12s ago │ │ ● Skills 8 installed · 3 │ │
|
|
105
|
+
│ │ ● Last upload 3m ago │ │ published │ │
|
|
106
|
+
│ ╰────────────────────────────╯ ╰────────────────────────────────╯ │
|
|
107
|
+
│ │
|
|
108
|
+
│ ╭─ Quick actions ───── ↑/↓ or j/k · Enter to choose · q to quit ─╮ │
|
|
109
|
+
│ │ › Share Codex session lore share-codex --session-file … │ │
|
|
110
|
+
│ │ Share Cowork session lore share-cowork │ │
|
|
111
|
+
│ │ Export latest Claude lore export │ │
|
|
112
|
+
│ │ Inspect background daemon lore status │ │
|
|
113
|
+
│ │ List installed skills lore skills list │ │
|
|
114
|
+
│ │ … │ │
|
|
115
|
+
│ ╰─────────────────────────────────────────────────────────────────╯ │
|
|
116
|
+
└────────────────────────────────────────────────────────────────────┘
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Picking an action exits the dashboard and re-enters the matching
|
|
120
|
+
subcommand exactly as if you had typed it yourself — auth checks,
|
|
121
|
+
metrics, and error formatting all flow through the same path.
|
|
122
|
+
|
|
123
|
+
The interactive flows (`lore login`, `lore enable` / `disable` /
|
|
124
|
+
`restart` / `status`, and the three share/export commands) also render
|
|
125
|
+
through Ink in TTY mode:
|
|
126
|
+
|
|
127
|
+
- **`lore login`** — three labelled steps (negotiating with WorkOS →
|
|
128
|
+
device code panel → polling), then a success box with the resolved
|
|
129
|
+
LaunchAgent paths. Distinct copy for timed-out / denied / expired.
|
|
130
|
+
On first login the device-code flow is followed by a one-screen
|
|
131
|
+
"Configure uploads" wizard that writes `repo` and `cwd` include
|
|
132
|
+
filters from your recent repos and directories.
|
|
133
|
+
- **`lore enable` / `disable` / `restart`** — spinner with mode-specific
|
|
134
|
+
copy while launchctl works, then a success or error MessageBox.
|
|
135
|
+
- **`lore status`** — two-panel view (health on the left, paths on the
|
|
136
|
+
right) with severity dots and a "Not healthy" callout pointing at
|
|
137
|
+
`lore restart` / `lore logs` when something is off.
|
|
138
|
+
- **`lore export` / `share-codex` / `share-cowork`** — four-step pipeline
|
|
139
|
+
display (resolving → uploading → parsing → updating visibility) with
|
|
140
|
+
the resulting URL highlighted in a success box.
|
|
141
|
+
|
|
142
|
+
### Disabling the TUI
|
|
143
|
+
|
|
144
|
+
The TUI is presentation only — every command produces identical
|
|
145
|
+
stdout in non-TTY contexts (scripts, CI, piped output). To force the
|
|
146
|
+
plain rendering even in a TTY:
|
|
147
|
+
|
|
148
|
+
- pass `--no-tui` at the top level: `lore --no-tui status`
|
|
149
|
+
- or set `LORE_NO_TUI=1` in the environment.
|
|
150
|
+
|
|
151
|
+
`lore status --json` always prints JSON and never mounts the TUI.
|
|
152
|
+
|
|
153
|
+
The plain path is also taken automatically whenever:
|
|
154
|
+
|
|
155
|
+
- stdout or stdin is not a TTY (piped, redirected, or scripted)
|
|
156
|
+
- `CI` is set to a truthy value
|
|
157
|
+
- `TERM=dumb`
|
|
158
|
+
|
|
159
|
+
### TUI architecture (for contributors)
|
|
160
|
+
|
|
161
|
+
See [AGENTS.md](./AGENTS.md) for the contributor guide on adding new
|
|
162
|
+
screens, the presentation/handler split, and the TTY-detection contract.
|
|
163
|
+
|
|
164
|
+
### TUI story runner
|
|
165
|
+
|
|
166
|
+
Use the terminal story runner to review seeded Ink states without touching
|
|
167
|
+
WorkOS, the Lore API, launchd, or local Lore config:
|
|
168
|
+
|
|
169
|
+
```sh
|
|
170
|
+
pnpm tui:stories # interactive browser
|
|
171
|
+
pnpm tui:stories --story dashboard/healthy
|
|
172
|
+
pnpm tui:stories --list # print available story ids
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Stories live under `src/tui/stories/` and import screen components rather
|
|
176
|
+
than `*Entrypoint.tsx` files. Keep new stories fixture-driven: pass explicit
|
|
177
|
+
state, timestamps, and no-op callbacks so story review never performs command
|
|
178
|
+
side effects. In the interactive runner, use ↑/↓ or j/k to choose a story,
|
|
179
|
+
Tab to focus the preview so nested controls own the keyboard, Shift+Tab or
|
|
180
|
+
Esc to return to the sidebar, and q to exit.
|
|
181
|
+
|
|
182
|
+
## Subcommands
|
|
183
|
+
|
|
184
|
+
- `lore` — opens the interactive dashboard in a TTY; prints help text
|
|
185
|
+
in non-TTY contexts.
|
|
186
|
+
- `lore login` — authorizes the CLI against your Lore workspace using WorkOS
|
|
187
|
+
CLI Auth's device-code flow. On macOS, also auto-runs `lore enable` to
|
|
188
|
+
install and start the background uploader; if that step fails, login still
|
|
189
|
+
succeeds and you can rerun `lore enable` manually.
|
|
190
|
+
- `lore logout` — removes the stored CLI tokens.
|
|
191
|
+
- `lore health` — calls the API health endpoint.
|
|
192
|
+
- `lore logs` — prints recent entries from the log file.
|
|
193
|
+
- `lore version` — prints the CLI version.
|
|
194
|
+
- `lore update` — runs the same update check as the background auto-updater,
|
|
195
|
+
waits for it to finish, and prints the result.
|
|
196
|
+
- `lore enable` — installs and starts the macOS background agent.
|
|
197
|
+
- `lore disable` — stops and removes the macOS background agent.
|
|
198
|
+
- `lore restart` — restarts the macOS background agent.
|
|
199
|
+
- `lore status` / `lore status --json` — shows background-agent health and recent activity. The plain output does not treat an idle process as broken just because there is no active upload at that instant.
|
|
200
|
+
- `lore configure` — re-enter the interactive wizard for picking the
|
|
201
|
+
repos and directories Lore auto-uploads from (the same flow shown on first
|
|
202
|
+
login). Requires an interactive terminal.
|
|
203
|
+
- `lore listen create <path>` — allowlist a directory for background auto-uploads.
|
|
204
|
+
- `lore listen list [--json]` — print the effective repo and cwd locations
|
|
205
|
+
the background agent may auto-upload from.
|
|
206
|
+
- `lore listen delete <path>` — stop uploading from a directory.
|
|
207
|
+
- `lore workspaces list` — calls `/api/whoami` and prints the WorkOS
|
|
208
|
+
workspaces the authenticated user currently belongs to. (Workspaces
|
|
209
|
+
are organizations in the underlying API contract.)
|
|
210
|
+
- `lore skills list` — lists skills visible to the authenticated workspace.
|
|
211
|
+
- `lore skills sync` — runs the foreground skill sync engine once: it scans
|
|
212
|
+
supported local skill roots, captures local changes privately, pulls accepted
|
|
213
|
+
remote updates for installed skills, and preserves subscriber edits as
|
|
214
|
+
proposals instead of overwriting them.
|
|
215
|
+
- `lore skills install <skill-id>` — installs a workspace-visible skill by its
|
|
216
|
+
stable `sk_…` id and records the local installation. Installing is
|
|
217
|
+
non-interactive and pipe-friendly: if the target `SKILL.md` already exists but
|
|
218
|
+
is managed by Lore (the same `sk_…`), it is overwritten with the remote body;
|
|
219
|
+
if it exists and is *not* managed by Lore, the install errors instead of
|
|
220
|
+
clobbering it. Use `lore skills sync` for conflict-preserving updates.
|
|
221
|
+
- `lore skills uninstall <skill-id>` — removes the managed local skill file and
|
|
222
|
+
clears the installation record.
|
|
223
|
+
- `lore skills publish <local-name-or-skill-id>` — publishes an authored skill
|
|
224
|
+
to the workspace, or submits an installed-skill edit as a proposal when the
|
|
225
|
+
caller is not the owner.
|
|
226
|
+
- `lore skills daemon` — hidden long-running worker used by supervised/dev
|
|
227
|
+
environments for skill sync. It does a startup sync, subscribes to skill SSE
|
|
228
|
+
events from `/api/events/stream`, falls back to polling, and performs a full
|
|
229
|
+
catch-up when the stream reports a truncated cursor.
|
|
230
|
+
- `lore export` — uploads a single Claude Code session on demand and prints a
|
|
231
|
+
JSON object with the thread URL. Use `--session-id <id>` to pick a specific
|
|
232
|
+
session, `--project <path>` to override the project lookup, and
|
|
233
|
+
`--visibility private|workspace|public` to set the resulting thread's
|
|
234
|
+
visibility. Use `--highlight <description>` to have the API resolve a
|
|
235
|
+
natural-language share highlight and return a `/thread/<id>#tb_…` block
|
|
236
|
+
anchor or range when it finds a match. The URL is also copied to the system clipboard when a clipboard
|
|
237
|
+
tool is available (`pbcopy` / `wl-copy` / `xclip` / `xsel` / `clip.exe`).
|
|
238
|
+
- `lore share-cowork` — shares a Claude Cowork local-agent-mode session
|
|
239
|
+
to Lore. Defaults to the current session when run from inside one
|
|
240
|
+
(e.g. by the Cowork agent itself); otherwise shares the most recent
|
|
241
|
+
local session under
|
|
242
|
+
`~/Library/Application Support/Claude/local-agent-mode-sessions/`.
|
|
243
|
+
Use `--session <session-id>` to share a specific session by id, or
|
|
244
|
+
`--list` to enumerate local sessions newest-first without sharing.
|
|
245
|
+
Re-running for the same session converges to the same thread (md5
|
|
246
|
+
dedup), so it's safe to retry. Prints the resulting `/thread/<id>`
|
|
247
|
+
URL on success.
|
|
248
|
+
|
|
249
|
+
## Dev vs prod
|
|
250
|
+
|
|
251
|
+
The CLI is environment-stamped at build time (esbuild `--define`), not via
|
|
252
|
+
runtime env vars. The published `@loredotlink/cli` on npm is pinned to prod;
|
|
253
|
+
anything built locally (`pnpm build`, `tsx`, `pnpm dev`) is pinned to dev.
|
|
254
|
+
|
|
255
|
+
Because both can be installed on the same machine, they keep separate state
|
|
256
|
+
dirs so they don't stomp each other:
|
|
257
|
+
|
|
258
|
+
| Env | State dir | Log file |
|
|
259
|
+
| ---- | --------------- | --------------------- |
|
|
260
|
+
| prod | `~/.lore/` | `~/.lore/log.txt` |
|
|
261
|
+
| dev | `~/.lore-dev/` or `LORE_DEV_STATE_DIR` when set by a supervised local stack | `<state-dir>/log.txt` |
|
|
262
|
+
|
|
263
|
+
`lore login` discovers WorkOS AuthKit from the Lore MCP resource metadata,
|
|
264
|
+
starts WorkOS's device-code flow, prints the verification URL and user code, and
|
|
265
|
+
polls WorkOS until it receives JWT access and refresh tokens. Token persistence,
|
|
266
|
+
legacy migration, OAuth discovery caching, and refresh-token rotation live in
|
|
267
|
+
`@lore/identity-store`, shared with the Lore plugin. The CLI stores the
|
|
268
|
+
canonical token record as `tokens.json` in the active state dir (for example,
|
|
269
|
+
`~/.lore-dev/tokens.json` in standalone local dev or
|
|
270
|
+
`~/.lore-dev-<stack>/tokens.json` under supervised `pnpm dev`) and caches OAuth discovery beside it as
|
|
271
|
+
`discovery-cache.json`. When the access token is expired or will expire within
|
|
272
|
+
10 seconds, authenticated commands use the refresh token to rotate a new access
|
|
273
|
+
token automatically. Transient refresh failures preserve the refresh token for a
|
|
274
|
+
later retry; only an AuthKit `invalid_grant` response clears local tokens and
|
|
275
|
+
requires login again. The CLI does not read token environment variables; use
|
|
276
|
+
`lore logout` to remove the stored tokens.
|
|
277
|
+
|
|
278
|
+
For local development, `pnpm dev <command>` first attempts
|
|
279
|
+
`pnpm bootstrap:dev-auth` so dev-only tokens are refreshed against the currently
|
|
280
|
+
running API process. If the API is unavailable, the bootstrap logs an error and
|
|
281
|
+
the requested command still runs.
|
|
282
|
+
|
|
283
|
+
Run `lore logs` to print the active log file path. In dev, log lines also
|
|
284
|
+
tee to stderr so you see them while iterating; in prod the file is the only
|
|
285
|
+
sink so installed users don't see noise on every command.
|
|
286
|
+
|
|
287
|
+
`pnpm dev` runs the CLI postinstall hook before starting so bundled dev skills
|
|
288
|
+
are refreshed in `~/.claude/skills` on each dev session.
|
|
289
|
+
|
|
290
|
+
### Skill sync end-to-end tests
|
|
291
|
+
|
|
292
|
+
Team skill sync has an opt-in acceptance suite that exercises an author's
|
|
293
|
+
computer and a subscriber's computer with isolated temporary homes and project
|
|
294
|
+
roots. It is intentionally separate from the default `pnpm test` glob so CI can
|
|
295
|
+
choose when to run the full acceptance loop explicitly:
|
|
296
|
+
|
|
297
|
+
```sh
|
|
298
|
+
pnpm --filter @loredotlink/cli test:skill-sync:e2e
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
The suite covers private capture, workspace publish/install, subscriber update
|
|
302
|
+
pulls, subscriber edit proposals, owner approval, uninstall cleanup, project-root
|
|
303
|
+
isolation, and daemon reconnect/catch-up behavior.
|
|
304
|
+
|
|
305
|
+
To point the CLI at a different API origin (e.g. through a Vite proxy or a
|
|
306
|
+
remote staging deployment), set `LORE_API_ORIGIN`. The override wins over the
|
|
307
|
+
built-in env defaults: `LORE_API_ORIGIN=http://localhost:8080 lore health`
|
|
308
|
+
will route through the web app's Vite proxy on 8080 to the API on 4000.
|