@tanagram/lore
v0.1.199
Published
Lore CLI
Downloads
18,827
Readme
Lore
Lore captures your Claude Code, Codex, and Cowork sessions and turns them into something your team can search, discuss, and build on.
Your AI coding sessions run on your machine. The Lore CLI watches for new ones and uploads them to your workspace automatically, so there is no copy-paste, no screenshots, no "save this thread" button to remember.
Get started
npm install -g @loredotlink/cli
lorelore opens a dashboard in your terminal. Sign in there once and, on
macOS, background uploads start immediately. On Linux, run lore configure
to pick which directories upload.
That's it. Keep coding. New sessions show up in your workspace automatically.
How privacy works
Private by default. Every session starts visible only to you. You choose per session whether to share it with your workspace or make it public. Workspace admins cannot override that choice.
You control what uploads. Lore only uploads sessions from directories
you allowlist. The first-run wizard pre-checks your three most recent
projects; nothing outside your allowlist is ever sent. Re-run the picker
any time with lore configure, or edit the list directly:
lore listen list # what's currently allowlisted
lore listen create ~/code/project # start uploading from here
lore listen delete ~/code/project # stopWhat a session contains. Your prompts, the assistant's responses, tool calls, file edits, and diffs, plus metadata like timestamps, model, and the repo it ran in. Diffs include the changed lines of the files you edited. Lore does not collect environment variables, secrets, or API keys.
Stop anytime. lore disable halts background uploads. lore logout
removes your stored credentials. You can delete any session, or your whole
account, from the web app.
Reference: upload filters
The Lore background agent evaluates ~/.lore/upload_filters.json
(~/.lore-dev/ in dev) before auto-uploading Claude Code sessions.
Missing config or an empty include allowlist means upload nothing. The cwd and repo
allowlists are a union: a session is location-allowed if it matches a
cwd rule OR a repo rule (so a non-git directory uploads via its cwd
even when repo rules also exist). When set, include.skills further
narrows that set (ANDed). Values within a dimension are ORed, and
exclude rules override includes.
The explicit commands (lore export, lore share-codex,
lore share-cowork) are user-initiated and upload the requested session
directly.
Adding repos and directories through the TUI is a convenience for writing
repo and cwd include filters. The post-login wizard shows your
most-recent Claude Code projects with the top three pre-checked: a project
inside a git repo is offered as its origin remote, and a non-repo
directory is offered by its path. Pressing Enter accepts them. lore configure re-enters that same interactive flow any time
(it's also one of the quick actions on the lore dashboard). For
scripted/non-interactive edits, use lore listen for directory filters;
lore listen list prints the effective repo and cwd upload locations:
lore listen create ~/code/projectA # watch ~/code/projectA
lore listen list # effective repo/cwd locations
lore listen list --json # for scripts
lore listen delete ~/code/projectA # stop uploading fromcwd matching uses path-separator-aware prefix-tree semantics, so adding
~/code covers ~/code/projectA, ~/code/projectA/src, etc., but
deliberately does not cover ~/code-other. The most-specific
matching entry wins, so you can have a broad personal ~/ allow plus a
narrower ~/work override that routes to a different org.
If a cwd include points at your entire home directory, lore listen list
prints a warning and suggests replacing it with narrower project paths. Lore
does not rewrite existing allowlists automatically.
Interactive TUI
Running lore with no subcommand drops you into an interactive Ink
dashboard when stdin and stdout are TTYs:
┌── lore — [email protected] · tanagram ─────────────────── v0.1.50 ──┐
│ │
│ ╭─ Daemon ──────────────────╮ ╭─ Workspace ─────────────────────╮ │
│ │ ● Status running │ │ ● User [email protected] │ │
│ │ ● Enabled yes │ │ ● Display Matt │ │
│ │ ● Running yes │ │ ● Org tanagram │ │
│ │ ● Heartbeat 12s ago │ │ ● Skills 8 installed · 3 │ │
│ │ ● Last upload 3m ago │ │ published │ │
│ ╰────────────────────────────╯ ╰────────────────────────────────╯ │
│ │
│ ╭─ Quick actions ───── ↑/↓ or j/k · Enter to choose · q to quit ─╮ │
│ │ › Share Codex session lore share-codex --session-file … │ │
│ │ Share Cowork session lore share-cowork │ │
│ │ Export latest Claude lore export │ │
│ │ Inspect background daemon lore status │ │
│ │ List installed skills lore skills list │ │
│ │ … │ │
│ ╰─────────────────────────────────────────────────────────────────╯ │
└────────────────────────────────────────────────────────────────────┘Picking an action exits the dashboard and re-enters the matching subcommand exactly as if you had typed it yourself — auth checks, metrics, and error formatting all flow through the same path.
The interactive flows (lore login, lore enable / disable /
restart / status, and the three share/export commands) also render
through Ink in TTY mode:
lore login— three labelled steps (negotiating with WorkOS → device code panel → polling), then a success box with the resolved LaunchAgent paths. Distinct copy for timed-out / denied / expired. On first login the device-code flow is followed by a one-screen "Configure uploads" wizard that writesrepoandcwdinclude filters from your recent repos and directories.lore enable/disable/restart— spinner with mode-specific copy while launchctl works, then a success or error MessageBox.lore status— two-panel view (health on the left, paths on the right) with severity dots and a "Not healthy" callout pointing atlore restart/lore logswhen something is off.lore export/share-codex/share-cowork— four-step pipeline display (resolving → uploading → parsing → updating visibility) with the resulting URL highlighted in a success box.
Disabling the TUI
The TUI is presentation only — every command produces identical stdout in non-TTY contexts (scripts, CI, piped output). To force the plain rendering even in a TTY:
- pass
--no-tuiat the top level:lore --no-tui status - or set
LORE_NO_TUI=1in the environment.
lore status --json always prints JSON and never mounts the TUI.
The plain path is also taken automatically whenever:
- stdout or stdin is not a TTY (piped, redirected, or scripted)
CIis set to a truthy valueTERM=dumb
TUI architecture (for contributors)
See AGENTS.md for the contributor guide on adding new screens, the presentation/handler split, and the TTY-detection contract.
TUI story runner
Use the terminal story runner to review seeded Ink states without touching WorkOS, the Lore API, launchd, or local Lore config:
pnpm tui:stories # interactive browser
pnpm tui:stories --story dashboard/healthy
pnpm tui:stories --list # print available story idsStories live under src/tui/stories/ and import screen components rather
than *Entrypoint.tsx files. Keep new stories fixture-driven: pass explicit
state, timestamps, and no-op callbacks so story review never performs command
side effects. In the interactive runner, use ↑/↓ or j/k to choose a story,
Tab to focus the preview so nested controls own the keyboard, Shift+Tab or
Esc to return to the sidebar, and q to exit.
Subcommands
lore— opens the interactive dashboard in a TTY; prints help text in non-TTY contexts.lore login— authorizes the CLI against your Lore workspace using WorkOS CLI Auth's device-code flow. On macOS, also auto-runslore enableto install and start the background uploader; if that step fails, login still succeeds and you can rerunlore enablemanually.lore logout— removes the stored CLI tokens.lore _refresh_auth_token— diagnostic command that forces an access-token refresh with the stored refresh token, prints any non-200 HTTP status and response body, and tells you whichwhoamicommand to run after success.lore health— calls the API health endpoint.lore logs— prints recent entries from the log file.lore version— prints the CLI version.lore update— runs the same update check as the background auto-updater, waits for it to finish, and prints the result.lore enable— installs and starts the macOS background agent.lore disable— stops and removes the macOS background agent.lore restart— restarts the macOS background agent.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.lore configure— re-enter the interactive wizard for picking the repos and directories Lore auto-uploads from (the same flow shown on first login). Requires an interactive terminal.lore listen create <path>— allowlist a directory for background auto-uploads.lore listen list [--json]— print the effective repo and cwd locations the background agent may auto-upload from.lore listen delete <path>— stop uploading from a directory.lore workspaces list— calls/api/whoamiand prints the WorkOS workspaces the authenticated user currently belongs to. (Workspaces are organizations in the underlying API contract.)lore skills list— lists skills visible to the authenticated workspace.lore skills sync— runs the foreground skill sync engine once: it scans supported local skill roots, captures local changes privately, pulls accepted remote updates for installed skills, and preserves subscriber edits as proposals instead of overwriting them.lore skills install <skill-id>— installs a workspace-visible skill by its stablesk_…id and records the local installation. Installing is non-interactive and pipe-friendly: if the targetSKILL.mdalready exists but is managed by Lore (the samesk_…), it is overwritten with the remote body; if it exists and is not managed by Lore, the install errors instead of clobbering it. Uselore skills syncfor conflict-preserving updates.lore skills uninstall <skill-id>— removes the managed local skill file and clears the installation record.lore skills publish <local-name-or-skill-id>— publishes an authored skill to the workspace, or submits an installed-skill edit as a proposal when the caller is not the owner.lore skills daemon— hidden long-running worker used by supervised/dev environments for skill sync. It does a startup sync, subscribes to skill SSE events from/api/events/stream, falls back to polling, and performs a full catch-up when the stream reports a truncated cursor.lore export— uploads a single Claude Code session on demand and prints a JSON object with the thread URL. Use--session-id <id>to pick a specific session,--project <path>to override the project lookup, and--visibility private|workspace|publicto set the resulting thread's visibility. Use--highlight <description>to have the API resolve a natural-language share highlight and return a/thread/<id>#tb_…block anchor or range when it finds a match. The URL is also copied to the system clipboard when a clipboard tool is available (pbcopy/wl-copy/xclip/xsel/clip.exe).lore share-cowork— shares a Claude Cowork local-agent-mode session to Lore. Defaults to the current session when run from inside one (e.g. by the Cowork agent itself); otherwise shares the most recent local session under~/Library/Application Support/Claude/local-agent-mode-sessions/. Use--session <session-id>to share a specific session by id, or--listto enumerate local sessions newest-first without sharing. Re-running for the same session converges to the same thread (md5 dedup), so it's safe to retry. Prints the resulting/thread/<id>URL on success.
Dev vs prod
The CLI is environment-stamped at build time (esbuild --define), not via
runtime env vars. The published @loredotlink/cli on npm is pinned to prod;
anything built locally (pnpm build, tsx, pnpm dev) is pinned to dev.
Because both can be installed on the same machine, they keep separate state dirs so they don't stomp each other:
| Env | State dir | Log file |
| ---- | --------------- | --------------------- |
| prod | ~/.lore/ | ~/.lore/cli.log.txt |
| dev | ~/.lore-dev/ or LORE_DEV_STATE_DIR when set by a supervised local stack | <state-dir>/cli.log.txt |
lore login discovers WorkOS AuthKit from the Lore MCP resource metadata,
starts WorkOS's device-code flow, prints the verification URL and user code, and
polls WorkOS until it receives JWT access and refresh tokens. Token persistence,
legacy migration, OAuth discovery caching, and refresh-token rotation live in
@lore/identity-store, shared with the Lore plugin. The CLI stores the
canonical token record as tokens.json in the active state dir (for example,
~/.lore-dev/tokens.json in standalone local dev or
~/.lore-dev-<stack>/tokens.json under supervised pnpm dev) and caches OAuth discovery beside it as
discovery-cache.json. When the access token is expired or will expire within
10 seconds, authenticated commands use the refresh token to rotate a new access
token automatically. Transient refresh failures preserve the refresh token for a
later retry; only an AuthKit invalid_grant response clears local tokens and
requires login again. The CLI does not read token environment variables; use
lore logout to remove the stored tokens.
For local development, pnpm dev <command> first attempts
pnpm bootstrap:dev-auth so dev-only tokens are refreshed against the currently
running API process. If the API is unavailable, the bootstrap logs an error and
the requested command still runs.
Run lore logs to print the active log file path. In dev, log lines also
tee to stderr so you see them while iterating; in prod the file is the only
sink so installed users don't see noise on every command.
pnpm dev runs the CLI postinstall hook before starting so bundled dev skills
are refreshed in ~/.claude/skills on each dev session.
Skill sync end-to-end tests
Team skill sync has an opt-in acceptance suite that exercises an author's
computer and a subscriber's computer with isolated temporary homes and project
roots. It is intentionally separate from the default pnpm test glob so CI can
choose when to run the full acceptance loop explicitly:
pnpm --filter @loredotlink/cli test:skill-sync:e2eThe suite covers private capture, workspace publish/install, subscriber update pulls, subscriber edit proposals, owner approval, uninstall cleanup, project-root isolation, and daemon reconnect/catch-up behavior.
To point the CLI at a different API origin (e.g. through a Vite proxy or a
remote staging deployment), set LORE_API_ORIGIN. The override wins over the
built-in env defaults: LORE_API_ORIGIN=http://localhost:8080 lore health
will route through the web app's Vite proxy on 8080 to the API on 4000.
