@cryptiklemur/lattice 1.25.1 → 1.26.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/README.md +94 -84
- package/client/src/components/project-settings/ProjectPlugins.tsx +117 -0
- package/client/src/components/project-settings/ProjectSettingsView.tsx +6 -0
- package/client/src/components/settings/GlobalPlugins.tsx +801 -0
- package/client/src/components/settings/SettingsView.tsx +3 -0
- package/client/src/components/sidebar/SettingsSidebar.tsx +3 -1
- package/client/src/stores/sidebar.ts +2 -2
- package/package.json +1 -1
- package/server/src/daemon.ts +1 -0
- package/server/src/handlers/plugins.ts +658 -0
- package/server/src/handlers/project-settings.ts +6 -0
- package/server/src/project/context-breakdown.ts +12 -0
- package/server/src/project/sdk-bridge.ts +6 -0
- package/shared/src/messages.ts +123 -2
- package/shared/src/models.ts +59 -0
- package/shared/src/project-settings.ts +2 -1
package/README.md
CHANGED
|
@@ -1,123 +1,136 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/screenshots/dashboard.png" alt="Lattice Dashboard" width="720" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h1 align="center">Lattice</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
Multi-machine agentic dashboard for Claude Code.<br/>
|
|
9
|
+
Monitor sessions, manage projects, track costs, and orchestrate across mesh-networked nodes.
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://www.npmjs.com/package/@cryptiklemur/lattice"><img src="https://img.shields.io/npm/v/@cryptiklemur/lattice?style=flat-square&color=blue" alt="npm version" /></a>
|
|
14
|
+
<a href="https://github.com/cryptiklemur/lattice/actions"><img src="https://img.shields.io/github/actions/workflow/status/cryptiklemur/lattice/ci.yml?style=flat-square&label=CI" alt="CI" /></a>
|
|
15
|
+
<a href="https://github.com/cryptiklemur/lattice/blob/main/LICENSE"><img src="https://img.shields.io/github/license/cryptiklemur/lattice?style=flat-square" alt="License" /></a>
|
|
16
|
+
<a href="https://github.com/cryptiklemur/lattice"><img src="https://img.shields.io/github/stars/cryptiklemur/lattice?style=flat-square" alt="Stars" /></a>
|
|
17
|
+
</p>
|
|
4
18
|
|
|
5
19
|
> **Alpha** — Lattice is under active development. APIs and features may change.
|
|
6
20
|
|
|
7
|
-
|
|
21
|
+
---
|
|
8
22
|
|
|
9
|
-
##
|
|
23
|
+
## Quick Start
|
|
10
24
|
|
|
11
|
-
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g @cryptiklemur/lattice
|
|
27
|
+
lattice
|
|
28
|
+
```
|
|
12
29
|
|
|
13
|
-
|
|
30
|
+
Opens at `http://localhost:7654`. Add projects through the UI or point it at a directory with a `CLAUDE.md` file.
|
|
14
31
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
- **Session management** — Browse, rename, delete, search, and resume sessions with date range filtering and hover previews
|
|
18
|
-
- **Analytics** — Cost over time, token flow, cache efficiency, session complexity, activity calendar, and 15+ chart types
|
|
19
|
-
- **Cost budget** — Daily spend tracking with configurable enforcement (warning, confirm, or hard block)
|
|
20
|
-
- **Theme system** — 23 base16 themes (12 dark, 11 light) with OKLCH color space for perceptual consistency
|
|
32
|
+
<details>
|
|
33
|
+
<summary>Install with Bun</summary>
|
|
21
34
|
|
|
22
|
-
|
|
35
|
+
```bash
|
|
36
|
+
bun install -g @cryptiklemur/lattice
|
|
37
|
+
lattice
|
|
38
|
+
```
|
|
23
39
|
|
|
24
|
-
|
|
40
|
+
</details>
|
|
25
41
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
- **Keyboard shortcuts** — Press `?` to see all shortcuts, `Ctrl+K` for command palette
|
|
29
|
-
- **Message actions** — Copy messages (raw markdown or plain text), start new sessions from any message
|
|
30
|
-
- **Auto-titling** — Sessions automatically get descriptive titles from the first exchange
|
|
31
|
-
- **Session hover previews** — Hover any session to see cost, duration, message count, model, and last message
|
|
42
|
+
<details>
|
|
43
|
+
<summary>Development setup</summary>
|
|
32
44
|
|
|
33
|
-
|
|
45
|
+
```bash
|
|
46
|
+
git clone https://github.com/cryptiklemur/lattice.git
|
|
47
|
+
cd lattice
|
|
48
|
+
bun install
|
|
49
|
+
bun run dev
|
|
50
|
+
```
|
|
34
51
|
|
|
35
|
-
|
|
52
|
+
Hot-reloads both server and client automatically.
|
|
36
53
|
|
|
37
|
-
|
|
38
|
-
- **Skill marketplace** — Search and install skills from [skills.sh](https://skills.sh)
|
|
39
|
-
- **Mesh networking** — Connect multiple machines, proxy sessions across nodes with automatic discovery
|
|
40
|
-
- **Configuration editor** — Edit CLAUDE.md, environment variables, rules, and permissions through the UI
|
|
41
|
-
- **Memory management** — View and edit Claude's project memories with frontmatter metadata
|
|
54
|
+
</details>
|
|
42
55
|
|
|
43
|
-
|
|
56
|
+
---
|
|
44
57
|
|
|
45
|
-
|
|
58
|
+
## Features
|
|
46
59
|
|
|
47
|
-
|
|
60
|
+
### Chat & Sessions
|
|
48
61
|
|
|
49
|
-
|
|
62
|
+
Send messages, approve tool use, and monitor context window usage with per-message token counts. Browse, rename, delete, and search sessions with date range filtering and hover previews. Sessions automatically get descriptive titles from the first exchange.
|
|
50
63
|
|
|
51
|
-
|
|
64
|
+

|
|
52
65
|
|
|
53
|
-
###
|
|
66
|
+
### Analytics & Cost Tracking
|
|
54
67
|
|
|
55
|
-
|
|
56
|
-
# With npm
|
|
57
|
-
npm install -g lattice-ai
|
|
68
|
+
Track spending, token usage, cache efficiency, and session patterns with 15+ chart types. Set daily cost budgets with configurable enforcement (warning, confirm, or hard block).
|
|
58
69
|
|
|
59
|
-
|
|
60
|
-
bun install -g lattice-ai
|
|
61
|
-
```
|
|
70
|
+

|
|
62
71
|
|
|
63
|
-
###
|
|
72
|
+
### Workspace
|
|
64
73
|
|
|
65
|
-
|
|
66
|
-
lattice
|
|
67
|
-
```
|
|
74
|
+
Open multiple sessions as tabs and switch between them. Split-pane via right-click context menu. Pin important messages with bookmarks — jump between them per-session or browse the global bookmarks view. Per-project tab state persists across navigation.
|
|
68
75
|
|
|
69
|
-
|
|
76
|
+
Press `?` for keyboard shortcuts, `Ctrl+K` for the command palette.
|
|
70
77
|
|
|
71
|
-
|
|
78
|
+

|
|
72
79
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
### Themes & Settings
|
|
81
|
+
|
|
82
|
+
23 base16 themes (12 dark, 11 light) with OKLCH color space. Configure MCP servers, environment variables, rules, permissions, and Claude settings through the UI.
|
|
83
|
+
|
|
84
|
+

|
|
85
|
+
|
|
86
|
+
### Infrastructure
|
|
79
87
|
|
|
80
|
-
|
|
88
|
+
- **Mesh networking** — Connect multiple machines with automatic discovery and session proxying
|
|
89
|
+
- **MCP servers** — Add, edit, and remove at global or project level
|
|
90
|
+
- **Skill marketplace** — Search and install from [skills.sh](https://skills.sh)
|
|
91
|
+
- **Memory management** — View and edit Claude's project memories
|
|
92
|
+
|
|
93
|
+
### Mobile
|
|
94
|
+
|
|
95
|
+
Responsive design with touch targets, swipe-to-open sidebar, and optimized layouts.
|
|
96
|
+
|
|
97
|
+
<img src="docs/screenshots/mobile-chat.png" width="300" alt="Mobile chat view" />
|
|
98
|
+
|
|
99
|
+
---
|
|
81
100
|
|
|
82
101
|
## Architecture
|
|
83
102
|
|
|
84
|
-
|
|
103
|
+
Bun monorepo with three packages:
|
|
85
104
|
|
|
86
|
-
| Package |
|
|
87
|
-
|
|
88
|
-
| `shared/` | TypeScript types, message protocol
|
|
89
|
-
| `server/` | Bun WebSocket server
|
|
90
|
-
| `client/` | React 19
|
|
105
|
+
| Package | Stack |
|
|
106
|
+
|---------|-------|
|
|
107
|
+
| `shared/` | TypeScript types, message protocol, constants |
|
|
108
|
+
| `server/` | Bun WebSocket server, analytics engine, mesh networking |
|
|
109
|
+
| `client/` | React 19, Vite, Tailwind, daisyUI, 23 themes |
|
|
91
110
|
|
|
92
|
-
|
|
111
|
+
Communication via typed WebSocket messages. Sessions managed through the [Claude Agent SDK](https://github.com/anthropics/claude-agent-sdk). Client state via Tanstack Store + Router.
|
|
93
112
|
|
|
94
113
|
### Security
|
|
95
114
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
115
|
+
| Feature | Detail |
|
|
116
|
+
|---------|--------|
|
|
117
|
+
| Authentication | Passphrase with scrypt hashing, 24-hour token expiration |
|
|
118
|
+
| Rate limiting | 100 messages per 10-second window per client |
|
|
119
|
+
| Attachments | 10MB upload limit |
|
|
120
|
+
| Bash commands | `cd` boundary-checked against project directory |
|
|
121
|
+
| Mesh pairing | Tokens expire after 5 minutes |
|
|
122
|
+
| Shutdown | Graceful drain of active streams |
|
|
102
123
|
|
|
103
124
|
### Testing
|
|
104
125
|
|
|
105
|
-
Playwright test suite covering onboarding, session flow, keyboard shortcuts, accessibility, message actions, and session previews.
|
|
106
|
-
|
|
107
126
|
```bash
|
|
108
|
-
#
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
# Run tests
|
|
112
|
-
bunx playwright test
|
|
113
|
-
|
|
114
|
-
# Single test file
|
|
115
|
-
bunx playwright test tests/session-flow.spec.ts
|
|
127
|
+
bun run dev # start server
|
|
128
|
+
bunx playwright test # run tests
|
|
116
129
|
```
|
|
117
130
|
|
|
118
|
-
|
|
131
|
+
Playwright suite covers onboarding, session flow, keyboard shortcuts, accessibility, message actions, and session previews.
|
|
119
132
|
|
|
120
|
-
|
|
133
|
+
## Configuration
|
|
121
134
|
|
|
122
135
|
| Path | Purpose |
|
|
123
136
|
|------|---------|
|
|
@@ -125,15 +138,12 @@ Lattice stores its config at `~/.lattice/config.json`. Global Claude settings ar
|
|
|
125
138
|
| `~/.lattice/bookmarks.json` | Message bookmarks across all sessions |
|
|
126
139
|
| `~/.claude/CLAUDE.md` | Global Claude instructions |
|
|
127
140
|
| `~/.claude.json` | Global MCP server configuration |
|
|
128
|
-
| `~/.claude/skills/` | Global skills directory |
|
|
129
|
-
|
|
130
|
-
Project-level settings are stored in each project's `.claude/` directory and `.mcp.json`.
|
|
131
141
|
|
|
132
|
-
|
|
142
|
+
**Environment variables:**
|
|
133
143
|
|
|
134
|
-
- `ANTHROPIC_API_KEY` — Optional.
|
|
135
|
-
- `DEBUG=lattice:*` —
|
|
136
|
-
- Server binds to `0.0.0.0:7654
|
|
144
|
+
- `ANTHROPIC_API_KEY` — Optional. Uses `claude setup-token` if not set.
|
|
145
|
+
- `DEBUG=lattice:*` — Structured debug logging.
|
|
146
|
+
- Server binds to `0.0.0.0:7654`. Override with `lattice --port <port>`.
|
|
137
147
|
|
|
138
148
|
## Contributing
|
|
139
149
|
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { useState, useEffect } from "react";
|
|
2
|
+
import { Blocks, Loader2 } from "lucide-react";
|
|
3
|
+
import { useWebSocket } from "../../hooks/useWebSocket";
|
|
4
|
+
import type { ProjectSettings, ServerMessage, PluginInfo } from "@lattice/shared";
|
|
5
|
+
|
|
6
|
+
interface ProjectPluginsProps {
|
|
7
|
+
settings: ProjectSettings;
|
|
8
|
+
updateSection: (section: string, data: Record<string, unknown>) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function ProjectPlugins({ settings, updateSection }: ProjectPluginsProps) {
|
|
12
|
+
var { send, subscribe, unsubscribe } = useWebSocket();
|
|
13
|
+
var [plugins, setPlugins] = useState<PluginInfo[]>([]);
|
|
14
|
+
var [loaded, setLoaded] = useState(false);
|
|
15
|
+
var [disabledPlugins, setDisabledPlugins] = useState<string[]>(settings.disabledPlugins ?? []);
|
|
16
|
+
var [saving, setSaving] = useState(false);
|
|
17
|
+
|
|
18
|
+
useEffect(function () {
|
|
19
|
+
function handleListResult(msg: ServerMessage) {
|
|
20
|
+
if (msg.type !== "plugin:list_result") return;
|
|
21
|
+
var data = msg as { type: "plugin:list_result"; plugins: PluginInfo[] };
|
|
22
|
+
setPlugins(data.plugins);
|
|
23
|
+
setLoaded(true);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
subscribe("plugin:list_result", handleListResult);
|
|
27
|
+
send({ type: "plugin:list" } as any);
|
|
28
|
+
|
|
29
|
+
return function () {
|
|
30
|
+
unsubscribe("plugin:list_result", handleListResult);
|
|
31
|
+
};
|
|
32
|
+
}, []);
|
|
33
|
+
|
|
34
|
+
useEffect(function () {
|
|
35
|
+
setDisabledPlugins(settings.disabledPlugins ?? []);
|
|
36
|
+
}, [settings.disabledPlugins]);
|
|
37
|
+
|
|
38
|
+
function handleToggle(pluginKey: string) {
|
|
39
|
+
var next: string[];
|
|
40
|
+
if (disabledPlugins.indexOf(pluginKey) !== -1) {
|
|
41
|
+
next = disabledPlugins.filter(function (k) { return k !== pluginKey; });
|
|
42
|
+
} else {
|
|
43
|
+
next = disabledPlugins.concat(pluginKey);
|
|
44
|
+
}
|
|
45
|
+
setDisabledPlugins(next);
|
|
46
|
+
setSaving(true);
|
|
47
|
+
updateSection("plugins", { disabledPlugins: next });
|
|
48
|
+
setTimeout(function () { setSaving(false); }, 500);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!loaded) {
|
|
52
|
+
return <div className="text-[13px] text-base-content/40 py-4">Loading...</div>;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (plugins.length === 0) {
|
|
56
|
+
return (
|
|
57
|
+
<div className="py-6 text-center text-[13px] text-base-content/30">
|
|
58
|
+
No plugins installed. Install plugins from Global Settings to use them in projects.
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
var enabledCount = plugins.length - disabledPlugins.length;
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<div className="py-2 space-y-4">
|
|
67
|
+
<div className="flex items-center justify-between">
|
|
68
|
+
<p className="text-[12px] text-base-content/40">
|
|
69
|
+
Toggle plugins on/off for this project. Disabled plugins won't load in new sessions.
|
|
70
|
+
</p>
|
|
71
|
+
{saving && <Loader2 size={12} className="text-primary animate-spin" />}
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<div className="text-[11px] text-base-content/30 mb-1">
|
|
75
|
+
{enabledCount} of {plugins.length} enabled
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<div className="space-y-1.5">
|
|
79
|
+
{plugins.map(function (plugin) {
|
|
80
|
+
var isDisabled = disabledPlugins.indexOf(plugin.key) !== -1;
|
|
81
|
+
return (
|
|
82
|
+
<div
|
|
83
|
+
key={plugin.key}
|
|
84
|
+
className={
|
|
85
|
+
"flex items-center gap-3 px-3 py-2.5 rounded-xl border transition-colors duration-[120ms] " +
|
|
86
|
+
(isDisabled
|
|
87
|
+
? "bg-base-300/30 border-base-content/8 opacity-50"
|
|
88
|
+
: "bg-base-300 border-base-content/15")
|
|
89
|
+
}
|
|
90
|
+
>
|
|
91
|
+
<Blocks size={14} className="text-base-content/25 flex-shrink-0" />
|
|
92
|
+
<div className="flex-1 min-w-0">
|
|
93
|
+
<div className="flex items-center gap-2">
|
|
94
|
+
<span className="text-[13px] font-bold text-base-content truncate">{plugin.name}</span>
|
|
95
|
+
<span className="text-[10px] font-mono px-1.5 py-0.5 rounded-md bg-base-content/8 text-base-content/40">
|
|
96
|
+
v{plugin.version}
|
|
97
|
+
</span>
|
|
98
|
+
</div>
|
|
99
|
+
<div className="text-[11px] text-base-content/30 mt-0.5">
|
|
100
|
+
{plugin.marketplace}
|
|
101
|
+
{plugin.skillCount > 0 ? " \u00B7 " + plugin.skillCount + " skill" + (plugin.skillCount !== 1 ? "s" : "") : ""}
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
<input
|
|
105
|
+
type="checkbox"
|
|
106
|
+
checked={!isDisabled}
|
|
107
|
+
onChange={function () { handleToggle(plugin.key); }}
|
|
108
|
+
className="toggle toggle-sm toggle-primary"
|
|
109
|
+
aria-label={(isDisabled ? "Enable" : "Disable") + " " + plugin.name}
|
|
110
|
+
/>
|
|
111
|
+
</div>
|
|
112
|
+
);
|
|
113
|
+
})}
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
@@ -12,6 +12,7 @@ import { ProjectRules } from "./ProjectRules";
|
|
|
12
12
|
import { ProjectMcp } from "./ProjectMcp";
|
|
13
13
|
import { ProjectMemory } from "./ProjectMemory";
|
|
14
14
|
import { ProjectNotifications } from "./ProjectNotifications";
|
|
15
|
+
import { ProjectPlugins } from "./ProjectPlugins";
|
|
15
16
|
|
|
16
17
|
var SECTION_CONFIG: Record<string, { title: string }> = {
|
|
17
18
|
general: { title: "General" },
|
|
@@ -20,6 +21,7 @@ var SECTION_CONFIG: Record<string, { title: string }> = {
|
|
|
20
21
|
environment: { title: "Environment" },
|
|
21
22
|
mcp: { title: "MCP Servers" },
|
|
22
23
|
skills: { title: "Skills" },
|
|
24
|
+
plugins: { title: "Plugins" },
|
|
23
25
|
rules: { title: "Rules" },
|
|
24
26
|
permissions: { title: "Permissions" },
|
|
25
27
|
memory: { title: "Memory" },
|
|
@@ -51,6 +53,10 @@ function renderSection(
|
|
|
51
53
|
return <ProjectSkills settings={settings} projectSlug={projectSlug} />;
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
if (section === "plugins") {
|
|
57
|
+
return <ProjectPlugins settings={settings} updateSection={updateSection} />;
|
|
58
|
+
}
|
|
59
|
+
|
|
54
60
|
if (section === "rules") {
|
|
55
61
|
return <ProjectRules settings={settings} updateSection={updateSection} />;
|
|
56
62
|
}
|