@tpsdev-ai/flair 0.29.0 → 0.31.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 +194 -377
- package/dist/cli-shim.cjs +1 -1
- package/dist/cli.js +1567 -366
- package/dist/deploy.js +241 -43
- package/dist/fabric-upgrade.js +77 -24
- package/dist/federation/scheduler.js +500 -0
- package/dist/fleet-verify.js +3 -3
- package/dist/install/clients.js +111 -53
- package/dist/lib/mcp-enable.js +2 -2
- package/dist/lib/mcp-spec.js +128 -0
- package/dist/lib/safe-snapshot-extract.js +231 -0
- package/dist/lib/scheduler-platform.js +128 -0
- package/dist/lib/xml-escape.js +54 -0
- package/dist/rem/scheduler.js +212 -55
- package/dist/rem/snapshot.js +13 -0
- package/dist/replication-convergence.js +505 -0
- package/dist/resources/A2AAdapter.js +1 -1
- package/dist/resources/Admin.js +1 -1
- package/dist/resources/AdminConnectors.js +1 -1
- package/dist/resources/AdminDashboard.js +1 -1
- package/dist/resources/AdminIdp.js +1 -1
- package/dist/resources/AdminInstance.js +1 -1
- package/dist/resources/AdminMemory.js +1 -1
- package/dist/resources/AdminPrincipals.js +1 -1
- package/dist/resources/Agent.js +1 -1
- package/dist/resources/AgentCard.js +1 -1
- package/dist/resources/AgentSeed.js +1 -1
- package/dist/resources/AttentionQuery.js +1 -1
- package/dist/resources/Credential.js +1 -1
- package/dist/resources/Federation.js +1 -1
- package/dist/resources/Instance.js +1 -1
- package/dist/resources/Integration.js +1 -1
- package/dist/resources/MCPClientMetadata.js +1 -1
- package/dist/resources/Memory.js +1 -1
- package/dist/resources/MemoryBootstrap.js +8 -9
- package/dist/resources/MemoryCandidate.js +168 -0
- package/dist/resources/MemoryConsolidate.js +1 -1
- package/dist/resources/MemoryDedupStats.js +1 -1
- package/dist/resources/MemoryFeed.js +1 -1
- package/dist/resources/MemoryGrant.js +1 -1
- package/dist/resources/MemoryMaintenance.js +1 -1
- package/dist/resources/MemoryReflect.js +2 -2
- package/dist/resources/MemoryReindex.js +1 -1
- package/dist/resources/MemoryUsage.js +1 -1
- package/dist/resources/OAuth.js +1 -1
- package/dist/resources/OAuthClient.js +1 -1
- package/dist/resources/OrgEvent.js +1 -1
- package/dist/resources/OrgEventCatchup.js +1 -1
- package/dist/resources/OrgEventMaintenance.js +1 -1
- package/dist/resources/PairingToken.js +1 -1
- package/dist/resources/Peer.js +1 -1
- package/dist/resources/Presence.js +3 -3
- package/dist/resources/RecordUsage.js +1 -1
- package/dist/resources/Relationship.js +1 -1
- package/dist/resources/SemanticSearch.js +18 -46
- package/dist/resources/SkillScan.js +1 -1
- package/dist/resources/Soul.js +1 -1
- package/dist/resources/SoulFeed.js +1 -1
- package/dist/resources/WorkspaceLatest.js +1 -1
- package/dist/resources/WorkspaceState.js +1 -1
- package/dist/resources/XAA.js +1 -1
- package/dist/resources/a2a-url.js +1 -1
- package/dist/resources/abstention.js +1 -1
- package/dist/resources/agent-auth.js +1 -1
- package/dist/resources/agentcard-fields.js +1 -1
- package/dist/resources/auth-middleware.js +1 -1
- package/dist/resources/embeddings-boot.js +14 -16
- package/dist/resources/embeddings-provider.js +15 -12
- package/dist/resources/federation-cleanup.js +5 -5
- package/dist/resources/federation-nonce-store.js +5 -5
- package/dist/resources/health.js +53 -25
- package/dist/resources/in-process.js +225 -0
- package/dist/resources/instance-identity.js +1 -1
- package/dist/resources/mcp-client-metadata-fields.js +1 -1
- package/dist/resources/mcp-handler.js +1 -1
- package/dist/resources/mcp-oauth.js +2 -2
- package/dist/resources/mcp-tools.js +23 -17
- package/dist/resources/memory-read-scope.js +1 -1
- package/dist/resources/memory-reflect-lib.js +3 -3
- package/dist/resources/memory-visibility.js +3 -3
- package/dist/resources/migration-boot.js +81 -11
- package/dist/resources/migrations/data-dir.js +205 -0
- package/dist/resources/migrations/embedding-stamp.js +3 -3
- package/dist/resources/migrations/graph-heal.js +2 -2
- package/dist/resources/migrations/ledger.js +1 -1
- package/dist/resources/migrations/progress.js +33 -0
- package/dist/resources/migrations/registry.js +14 -5
- package/dist/resources/migrations/runner.js +93 -13
- package/dist/resources/migrations/state.js +13 -2
- package/dist/resources/migrations/synthetic-test-migration.js +1 -1
- package/dist/resources/migrations/visibility-backfill.js +232 -0
- package/dist/resources/models-dir.js +18 -9
- package/dist/resources/record-types.js +28 -0
- package/dist/resources/semantic-retrieval-core.js +6 -5
- package/dist/resources/usage-recording.js +1 -1
- package/dist/src/lib/scheduler-platform.js +128 -0
- package/dist/src/lib/xml-escape.js +54 -0
- package/dist/src/rem/scheduler.js +397 -0
- package/docs/deploying-on-fabric.md +267 -0
- package/docs/deployment.md +6 -0
- package/docs/embedding-in-a-harper-app.md +299 -0
- package/docs/federation.md +61 -4
- package/docs/integrations.md +3 -0
- package/docs/mcp-clients.md +16 -7
- package/docs/quickstart.md +80 -54
- package/docs/releasing.md +72 -38
- package/docs/supply-chain-policy.md +40 -4
- package/docs/troubleshooting.md +24 -0
- package/docs/upgrade.md +100 -5
- package/package.json +4 -14
- package/schemas/memory.graphql +9 -1
- package/templates/bin/flair-federation-sync.sh.tmpl +28 -0
- package/templates/launchd/dev.flair.federation.sync.plist.tmpl +47 -0
- package/templates/systemd/flair-federation-sync.service.tmpl +21 -0
- package/templates/systemd/flair-federation-sync.timer.tmpl +16 -0
- package/dist/resources/rerank-provider.js +0 -569
- package/docs/rerank-provisioning.md +0 -101
package/docs/federation.md
CHANGED
|
@@ -81,15 +81,69 @@ flair federation pair https://<fabric-node>:19926/<instance-name> --token-from .
|
|
|
81
81
|
|
|
82
82
|
Replace `<fabric-node>`, `<instance-name>`, and `<hub-admin-password>` with your actual values.
|
|
83
83
|
|
|
84
|
+
Running the hub on Fabric has its own considerations — port derivation against a managed
|
|
85
|
+
`443` endpoint, why the sync driver can only be installed on a machine you control, and
|
|
86
|
+
the observability limits of a node you have no shell on. See
|
|
87
|
+
[`docs/deploying-on-fabric.md`](deploying-on-fabric.md).
|
|
88
|
+
|
|
84
89
|
## Sync
|
|
85
90
|
|
|
86
|
-
Push local changes to the hub:
|
|
91
|
+
Push local changes to the hub, once:
|
|
87
92
|
|
|
88
93
|
```bash
|
|
89
94
|
flair federation sync --admin-pass <password>
|
|
90
95
|
# Output: ✅ Synced 12 records (0 skipped) in 145ms
|
|
91
96
|
```
|
|
92
97
|
|
|
98
|
+
### Keeping it synced
|
|
99
|
+
|
|
100
|
+
`flair federation sync` is one-shot and `flair federation watch` only runs
|
|
101
|
+
while its terminal is open. Neither survives a logout, so a spoke that is only
|
|
102
|
+
ever synced by hand looks paired but stops replicating — enable the scheduled
|
|
103
|
+
driver instead:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
flair federation sync enable # every 300s by default
|
|
107
|
+
flair federation sync enable --interval 900 # or pick your own cadence
|
|
108
|
+
flair federation sync status # is anything actually driving sync?
|
|
109
|
+
flair federation sync disable
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
This installs a **periodic one-shot**: a launchd job (`StartInterval`) on
|
|
113
|
+
macOS, a systemd user timer (`OnUnitActiveSec`) on Linux, each invoking
|
|
114
|
+
`flair federation sync` on the interval. It is deliberately not a supervised
|
|
115
|
+
long-lived watcher — the sync holds no state between runs, so a resident
|
|
116
|
+
process would buy nothing, and a supervisor cannot restart a process that
|
|
117
|
+
hangs rather than exits. The trade-off is latency, and `--interval` is the
|
|
118
|
+
knob. The first sync runs immediately on enable.
|
|
119
|
+
|
|
120
|
+
`flair federation watch` is unchanged and still the right tool for an
|
|
121
|
+
interactive "watch it sync while I debug" session.
|
|
122
|
+
|
|
123
|
+
**Credentials.** The scheduler never writes a password into a unit file. It
|
|
124
|
+
stores the *path* given to `--admin-pass-file` (defaulting to
|
|
125
|
+
`~/.flair/admin-pass` when that exists) and the CLI reads the file at run time,
|
|
126
|
+
refusing it unless it is owner-only (`chmod 600`). Pass `--no-credentials` to
|
|
127
|
+
wire none at all.
|
|
128
|
+
|
|
129
|
+
### Is anything driving sync?
|
|
130
|
+
|
|
131
|
+
`flair federation status` reports the driver alongside the peer table, because
|
|
132
|
+
"no peer has merged in 24h" has two completely different causes:
|
|
133
|
+
|
|
134
|
+
| What you see | What it means | What to do |
|
|
135
|
+
|---|---|---|
|
|
136
|
+
| `Sync driver: active` | A managed driver is loaded and syncs are landing | Nothing |
|
|
137
|
+
| `Sync driver: active … but no peer contact in <window>` | Sync **is** running; the runs are not reaching the peer | `flair federation reachability`, then the driver log |
|
|
138
|
+
| `Sync driver: NONE` | Nothing has run sync since you paired | `flair federation sync enable` |
|
|
139
|
+
| `Sync driver: INSTALLED BUT NOT LOADED` | Unit files exist, the service manager never loaded them | `flair federation sync enable` |
|
|
140
|
+
| `Sync driver: none managed by Flair — but syncs are landing` | A cron entry / hand-written unit is driving it | Nothing |
|
|
141
|
+
|
|
142
|
+
The check is local to the machine running the CLI, so it is omitted when
|
|
143
|
+
`--target` points at a remote instance.
|
|
144
|
+
|
|
145
|
+
Driver logs: `~/.flair/logs/federation-sync.{stdout,stderr}.log`.
|
|
146
|
+
|
|
93
147
|
## Security
|
|
94
148
|
|
|
95
149
|
### Signed requests
|
|
@@ -125,10 +179,13 @@ Records with `updatedAt` more than 5 minutes in the future are rejected. This pr
|
|
|
125
179
|
|
|
126
180
|
| Command | Description |
|
|
127
181
|
|---------|-------------|
|
|
128
|
-
| `flair federation status` | Show instance identity
|
|
182
|
+
| `flair federation status` | Show instance identity, peer connections, and whether anything is driving sync |
|
|
129
183
|
| `flair federation pair <hub-url> --token-from <file>` | Pair this spoke with a hub using a token triple file (or `-` for stdin) |
|
|
130
184
|
| `flair federation sync` | Push local changes to the hub (one-shot) |
|
|
131
|
-
| `flair federation
|
|
185
|
+
| `flair federation sync enable [--interval <s>] [--admin-pass-file <path>]` | Install the scheduled sync driver (launchd on macOS, systemd timer on Linux) |
|
|
186
|
+
| `flair federation sync disable [--remove-shim]` | Remove the scheduled sync driver |
|
|
187
|
+
| `flair federation sync status` | Show whether the driver is installed and genuinely active |
|
|
188
|
+
| `flair federation watch [--interval <s>]` | Run sync in a foreground loop for an interactive session (default 30s) |
|
|
132
189
|
| `flair federation reachability` | Probe local instance + each paired peer (read-only) |
|
|
133
190
|
| `flair federation token [--ttl <min>]` | Generate a one-time pairing token triple (hub only) |
|
|
134
191
|
|
|
@@ -174,6 +231,6 @@ flair federation unpin <instanceId>
|
|
|
174
231
|
## Limitations (1.0)
|
|
175
232
|
|
|
176
233
|
- **HTTP push only** — no persistent WebSocket connections or real-time sync
|
|
177
|
-
- **
|
|
234
|
+
- **Polled sync** — `flair federation sync enable` schedules a periodic one-shot (launchd / systemd, default 300s); there is no write-path trigger, so a new memory replicates on the next tick rather than immediately
|
|
178
235
|
- **Single hub** — spoke-to-spoke sync goes through the hub
|
|
179
236
|
- **Record-level LWW** — not field-level; concurrent edits to different fields of the same record may lose data
|
package/docs/integrations.md
CHANGED
|
@@ -24,6 +24,8 @@ Where Flair already runs. Each integration shown here is a working surface — t
|
|
|
24
24
|
|
|
25
25
|
Don't see your harness? If it speaks **MCP** — Flair already works with `flair-mcp`. If it has a **custom memory protocol** like LangGraph's `BaseStore` or CrewAI's `RAGStorage`, an adapter is a ~200-line package; [open an issue](https://github.com/tpsdev-ai/flair/issues) or [send a PR](https://github.com/tpsdev-ai/flair).
|
|
26
26
|
|
|
27
|
+
**Already running on Harper?** Every surface above reaches Flair over HTTP. If your application is itself a Harper app, you can skip the network entirely — load Flair as a component of the same instance and call its resources in-process. See [embedding-in-a-harper-app.md](embedding-in-a-harper-app.md), which also covers the table-vs-resource distinction that decides whether your memories are scoped.
|
|
28
|
+
|
|
27
29
|
**Adjacent: memory bridges** — for moving memories between Flair and another memory product. Five bridges ship today (Mem0, ChatGPT exports, claude-project files, agentic-stack, markdown); see [bridges.md](bridges.md). Bridges are import/export plumbing, not live orchestrator integrations.
|
|
28
30
|
|
|
29
31
|
---
|
|
@@ -191,6 +193,7 @@ If it has a custom memory protocol, the adapter pattern is small (~200 lines). L
|
|
|
191
193
|
## See also
|
|
192
194
|
|
|
193
195
|
- [Quickstart](quickstart.md) — `flair init` to working memory in 30 seconds
|
|
196
|
+
- [Embedding in a Harper app](embedding-in-a-harper-app.md) — run Flair as a component of your own Harper instance and call it in-process
|
|
194
197
|
- [Memory bridges](bridges.md) — import/export Flair ↔ Mem0, ChatGPT, claude-project, markdown, agentic-stack (five bridges shipped)
|
|
195
198
|
- [Federation](federation.md) — pair instances peer-to-peer for cross-machine sync
|
|
196
199
|
- [Supply-chain policy](supply-chain-policy.md) — what we do to keep this list of integrations safe
|
package/docs/mcp-clients.md
CHANGED
|
@@ -38,7 +38,9 @@ Flair runs as a local server at `http://127.0.0.1:19926` by default. The MCP ser
|
|
|
38
38
|
|
|
39
39
|
Pick whichever you use. The MCP server is the same package; only the config syntax differs.
|
|
40
40
|
|
|
41
|
-
> **Pin the version.**
|
|
41
|
+
> **Pin the version.** An unpinned `@tpsdev-ai/flair-mcp` re-resolves to whatever is currently published on *every* agent session, so any future publish reaches your machine silently, with no lockfile and no review step in the path. `flair init` wires clients to a **pinned** spec on purpose, and every MCP-server config snippet below is written the same way: `@tpsdev-ai/flair-mcp@<version>`.
|
|
42
|
+
>
|
|
43
|
+
> Replace `<version>` with the version you intend to run — the one you already have is `flair --version` — and bump it deliberately. Leaving the literal `<version>` in place fails loudly at `npx`, which is the intended failure: better than a config that looks pinned and isn't. `flair init` is the easier path and fills this in for you.
|
|
42
44
|
|
|
43
45
|
### Claude Code
|
|
44
46
|
|
|
@@ -47,14 +49,14 @@ The canonical approach is the `claude mcp add` CLI (writes to `~/.claude.json`):
|
|
|
47
49
|
```bash
|
|
48
50
|
claude mcp add flair --scope user \
|
|
49
51
|
-e FLAIR_AGENT_ID=my-project \
|
|
50
|
-
-- npx -y @tpsdev-ai/flair-mcp
|
|
52
|
+
-- npx -y @tpsdev-ai/flair-mcp@<version>
|
|
51
53
|
```
|
|
52
54
|
|
|
53
55
|
Verify:
|
|
54
56
|
|
|
55
57
|
```bash
|
|
56
58
|
claude mcp list
|
|
57
|
-
# → flair (stdio, npx -y @tpsdev-ai/flair-mcp)
|
|
59
|
+
# → flair (stdio, npx -y @tpsdev-ai/flair-mcp@<version>)
|
|
58
60
|
```
|
|
59
61
|
|
|
60
62
|
Or, if you prefer the project-scoped `.mcp.json` checked into your repo:
|
|
@@ -64,7 +66,7 @@ Or, if you prefer the project-scoped `.mcp.json` checked into your repo:
|
|
|
64
66
|
"mcpServers": {
|
|
65
67
|
"flair": {
|
|
66
68
|
"command": "npx",
|
|
67
|
-
"args": ["-y", "@tpsdev-ai/flair-mcp"],
|
|
69
|
+
"args": ["-y", "@tpsdev-ai/flair-mcp@<version>"],
|
|
68
70
|
"env": {
|
|
69
71
|
"FLAIR_AGENT_ID": "my-project"
|
|
70
72
|
}
|
|
@@ -116,7 +118,14 @@ Or wire it by hand — add a `SessionStart` hook to `~/.claude/settings.json`:
|
|
|
116
118
|
}
|
|
117
119
|
```
|
|
118
120
|
|
|
119
|
-
Swap `me` for your `FLAIR_AGENT_ID`.
|
|
121
|
+
Swap `me` for your `FLAIR_AGENT_ID`. Unlike the MCP-server snippets above, this
|
|
122
|
+
one is shown **unpinned**, because that is what `flair hook install` writes and
|
|
123
|
+
what the tooling recognises: `flair hook status` matches the exact unpinned
|
|
124
|
+
command, so a hand-pinned hook reports `wired: false` there (while `flair
|
|
125
|
+
doctor` still sees it). Pinning this line is therefore not yet supported —
|
|
126
|
+
prefer `flair hook install`.
|
|
127
|
+
|
|
128
|
+
The hook reads Claude Code's SessionStart
|
|
120
129
|
payload on stdin, calls Flair's `bootstrap` (soul + relevant memories +
|
|
121
130
|
predicted context, scoped to your project by the session's working directory),
|
|
122
131
|
and emits it as `hookSpecificOutput.additionalContext` — which Claude Code
|
|
@@ -143,7 +152,7 @@ Edit `~/.gemini/settings.json` (create it if absent):
|
|
|
143
152
|
"mcpServers": {
|
|
144
153
|
"flair": {
|
|
145
154
|
"command": "npx",
|
|
146
|
-
"args": ["-y", "@tpsdev-ai/flair-mcp"],
|
|
155
|
+
"args": ["-y", "@tpsdev-ai/flair-mcp@<version>"],
|
|
147
156
|
"env": {
|
|
148
157
|
"FLAIR_AGENT_ID": "my-project"
|
|
149
158
|
}
|
|
@@ -165,7 +174,7 @@ Edit `~/.codex/config.toml` (create it if absent):
|
|
|
165
174
|
```toml
|
|
166
175
|
[mcp_servers.flair]
|
|
167
176
|
command = "npx"
|
|
168
|
-
args = ["-y", "@tpsdev-ai/flair-mcp"]
|
|
177
|
+
args = ["-y", "@tpsdev-ai/flair-mcp@<version>"]
|
|
169
178
|
|
|
170
179
|
[mcp_servers.flair.env]
|
|
171
180
|
FLAIR_AGENT_ID = "my-project"
|
package/docs/quickstart.md
CHANGED
|
@@ -2,37 +2,50 @@
|
|
|
2
2
|
|
|
3
3
|
From zero to a persistent agent memory in five minutes.
|
|
4
4
|
|
|
5
|
-
## 0.
|
|
5
|
+
## 0. Prerequisites
|
|
6
6
|
|
|
7
|
-
**Node.js 22 or newer.**
|
|
7
|
+
**Node.js 22 or newer.** No Docker, no database to install, no API keys — Flair runs in a single process and computes embeddings locally.
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
node --version # v22.x.x or
|
|
10
|
+
node --version # v22.x.x or newer
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Need it? [nodejs.org](https://nodejs.org/), `nvm install 22`, or `brew install node`.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
**A user-writable npm global prefix.** Do not install Flair with `sudo`. A root-owned install cannot write the embedding model into its own package directory, and semantic search silently falls back to keyword-only matching. `nvm` gives you a user-owned prefix already; otherwise:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
mkdir -p ~/.npm-global
|
|
19
|
+
npm config set prefix ~/.npm-global
|
|
20
|
+
export PATH="$HOME/.npm-global/bin:$PATH" # add this to ~/.zshrc or ~/.bashrc
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 1. Install
|
|
16
24
|
|
|
17
25
|
```bash
|
|
18
26
|
npm install -g @tpsdev-ai/flair
|
|
19
27
|
```
|
|
20
28
|
|
|
21
|
-
`flair`, `flair-mcp
|
|
29
|
+
One install gives you `flair`, `flair-mcp` and the client library.
|
|
22
30
|
|
|
23
|
-
## 2. Bootstrap Flair
|
|
31
|
+
## 2. Bootstrap Flair and register an agent
|
|
24
32
|
|
|
25
33
|
```bash
|
|
26
|
-
flair init
|
|
34
|
+
flair init --agent local
|
|
27
35
|
```
|
|
28
36
|
|
|
29
|
-
|
|
37
|
+
> **Pass `--agent`.** A bare `flair init` bootstraps the instance and stops there — it prints `✅ Flair initialized (no agent registered)` and creates no keypair, no soul, and no MCP wiring.
|
|
38
|
+
|
|
39
|
+
First run does six things:
|
|
30
40
|
|
|
31
|
-
1. Installs the embedded Harper
|
|
32
|
-
2. Downloads the local embedding model
|
|
41
|
+
1. Installs the embedded Harper memory store into `~/.flair/data/`.
|
|
42
|
+
2. Downloads the local embedding model — about 80 MB, first run only.
|
|
33
43
|
3. Starts Flair as a launchd / systemd service on port 19926.
|
|
34
|
-
4.
|
|
35
|
-
5.
|
|
44
|
+
4. Generates the agent's Ed25519 keypair in `~/.flair/keys/` and registers it.
|
|
45
|
+
5. Wires every MCP client it detects — Claude Code, Cursor, Codex CLI, Gemini CLI — to `npx -y @tpsdev-ai/flair-mcp`, then smoke-tests it. `--no-mcp` skips this.
|
|
46
|
+
6. Opens a short **soul wizard** so your agent knows who it is.
|
|
47
|
+
|
|
48
|
+
It also generates a Harper admin password and writes it to `~/.flair/admin-pass` (mode 0600). The CLI prints that **path**, never the value — read the file when a command needs the password, and prefer `--admin-pass-file ~/.flair/admin-pass` over pasting it into a command line.
|
|
36
49
|
|
|
37
50
|
The soul wizard offers a few shapes:
|
|
38
51
|
|
|
@@ -49,7 +62,7 @@ The soul wizard offers a few shapes:
|
|
|
49
62
|
(s) Skip — set up later; `flair doctor` will nudge
|
|
50
63
|
```
|
|
51
64
|
|
|
52
|
-
Pick the template that matches how you'll use
|
|
65
|
+
Pick the template that matches how you'll use the agent. Edit or replace any entry later with `flair soul set`. The wizard is skipped automatically in a non-interactive shell, and by `--skip-soul`.
|
|
53
66
|
|
|
54
67
|
## 3. Confirm it's running
|
|
55
68
|
|
|
@@ -57,61 +70,68 @@ Pick the template that matches how you'll use this agent. You can edit or replac
|
|
|
57
70
|
flair status
|
|
58
71
|
```
|
|
59
72
|
|
|
60
|
-
A bare `flair status` (no agent, no admin credentials) only shows the public health
|
|
61
|
-
summary:
|
|
62
|
-
|
|
63
73
|
```
|
|
64
|
-
Flair vX.Y.Z —
|
|
65
|
-
URL
|
|
74
|
+
Flair vX.Y.Z — ✓ running PID 12345 · uptime 0m
|
|
75
|
+
URL http://127.0.0.1:19926
|
|
66
76
|
|
|
67
|
-
|
|
68
|
-
|
|
77
|
+
Memory
|
|
78
|
+
Total 0
|
|
79
|
+
Durability permanent:0 · persistent:0 · standard:0 · ephemeral:0
|
|
80
|
+
Archived 0
|
|
69
81
|
|
|
70
|
-
|
|
82
|
+
Agents
|
|
83
|
+
Total 1 — local
|
|
71
84
|
|
|
72
|
-
|
|
85
|
+
REM
|
|
86
|
+
Nightly disabled
|
|
73
87
|
|
|
74
|
-
|
|
75
|
-
flair status --agent local
|
|
76
|
-
```
|
|
88
|
+
Federation not configured
|
|
77
89
|
|
|
78
|
-
|
|
79
|
-
Flair vX.Y.Z — 🟢 running (PID 12345, uptime 1m)
|
|
80
|
-
URL: http://127.0.0.1:19926
|
|
90
|
+
Bridges none installed
|
|
81
91
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
Agents:
|
|
87
|
-
1 total — local
|
|
88
|
-
|
|
89
|
-
Soul:
|
|
90
|
-
3 entries — 0 critical / 0 high / 3 standard / 0 low
|
|
92
|
+
Disk
|
|
93
|
+
Data ~/.flair/data — 0 B
|
|
94
|
+
Snapshots ~/.flair/snapshots — 0 B
|
|
91
95
|
|
|
92
96
|
✓ all checks passing
|
|
93
97
|
```
|
|
94
98
|
|
|
99
|
+
You will also see a **Soul** section if you completed the wizard in step 2.
|
|
100
|
+
|
|
101
|
+
`✓` means healthy. `⚠` means something is worth looking at, and the warning names the command that fixes it. For `✗ unreachable`, see [troubleshooting.md](troubleshooting.md).
|
|
102
|
+
|
|
95
103
|
## 4. Write your first memory
|
|
96
104
|
|
|
97
105
|
```bash
|
|
98
|
-
flair memory add --agent local
|
|
106
|
+
flair memory add --agent local "Harper v5 sandbox blocks node:module but process.dlopen works"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"id": "local-1785277247486",
|
|
112
|
+
"written": true,
|
|
113
|
+
"deduplicated": false
|
|
114
|
+
}
|
|
99
115
|
```
|
|
100
116
|
|
|
101
|
-
Flair
|
|
117
|
+
Flair embedded the text locally on write. No network calls.
|
|
102
118
|
|
|
103
119
|
## 5. Find it back by meaning
|
|
104
120
|
|
|
105
121
|
```bash
|
|
106
|
-
flair
|
|
122
|
+
flair search --agent local "native addon loading in sandboxed runtimes"
|
|
107
123
|
```
|
|
108
124
|
|
|
109
125
|
```
|
|
110
126
|
Harper v5 sandbox blocks node:module but process.dlopen works
|
|
111
|
-
(2026-
|
|
127
|
+
( 2026-07-28 · standard · 100% )
|
|
112
128
|
```
|
|
113
129
|
|
|
114
|
-
|
|
130
|
+
You searched for a concept, not the keywords. The line under each hit is its creation date, durability tier, and rank score.
|
|
131
|
+
|
|
132
|
+
> The percentage is a **rank-fusion score, not a similarity**. It is normalized so the top result is always near 100%. Read it as ordering within these results, never as confidence that the match is good.
|
|
133
|
+
|
|
134
|
+
Add `--explain` to see the ranking inputs, or `--limit`, `--tag`, `--since 7d` to narrow the search. `flair memory search` runs the same query but always prints raw JSON — use it when piping to a script.
|
|
115
135
|
|
|
116
136
|
## 6. Give your agent context on boot
|
|
117
137
|
|
|
@@ -119,35 +139,41 @@ flair memory search --agent local --q "native addon loading in sandboxed runtime
|
|
|
119
139
|
flair bootstrap --agent local --max-tokens 2000
|
|
120
140
|
```
|
|
121
141
|
|
|
122
|
-
|
|
142
|
+
```
|
|
143
|
+
## Recent Context
|
|
144
|
+
📝 Harper v5 sandbox blocks node:module but process.dlopen works (2026-07-28)
|
|
145
|
+
✓ budget 20/2000 tokens (1%) · ✓ 1 included · ✓ 0 truncated
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Soul entries and relevant memories, in one block sized to a token budget. Paste it into any LLM session — Claude Code, Codex, Cursor, an API call — to hand the agent its identity and memory in one shot.
|
|
123
149
|
|
|
124
|
-
|
|
150
|
+
Using Claude Code? Add this to your `CLAUDE.md`:
|
|
125
151
|
|
|
126
152
|
```
|
|
127
153
|
At the start of every session, run mcp__flair__bootstrap before responding.
|
|
128
154
|
```
|
|
129
155
|
|
|
130
|
-
With the MCP server wired up
|
|
156
|
+
With the MCP server wired up — `flair init` does this automatically for every client it detects — Claude Code runs bootstrap on every new session. See the [integration section in README.md](../README.md#integration).
|
|
131
157
|
|
|
132
158
|
## What's next
|
|
133
159
|
|
|
134
160
|
| You want to... | Go to |
|
|
135
161
|
|----------------|-------|
|
|
136
162
|
| Add more agents to the same instance | `flair agent add <id>` |
|
|
137
|
-
|
|
|
138
|
-
| Import memories from agentic-stack / Mem0 / etc. | [
|
|
139
|
-
| Sync memories across machines | [
|
|
163
|
+
| Keep a memory owner-only | `flair memory add --visibility private` — reads are otherwise open to every agent on the instance ([auth.md](auth.md)) |
|
|
164
|
+
| Import memories from agentic-stack / Mem0 / etc. | [bridges.md](bridges.md) |
|
|
165
|
+
| Sync memories across machines | [federation.md](federation.md) |
|
|
140
166
|
| Integrate with OpenClaw, Claude Code, Cursor | [README.md#integration](../README.md#integration) |
|
|
141
|
-
| Fix something that isn't working | [
|
|
142
|
-
| Upgrade to a new version | `flair upgrade
|
|
167
|
+
| Fix something that isn't working | `flair doctor`, then [troubleshooting.md](troubleshooting.md) |
|
|
168
|
+
| Upgrade to a new version | `flair upgrade` (restarts automatically) or [upgrade.md](upgrade.md) |
|
|
143
169
|
|
|
144
170
|
## If you change your mind
|
|
145
171
|
|
|
146
172
|
```bash
|
|
147
|
-
flair stop # stop the service
|
|
173
|
+
flair stop # stop the service, keep data
|
|
148
174
|
flair restart # restart
|
|
149
|
-
flair uninstall # remove the service
|
|
150
|
-
flair uninstall --purge # remove everything including data and keys
|
|
175
|
+
flair uninstall # remove the service, keep data and keys
|
|
176
|
+
flair uninstall --purge # remove everything, including data and keys
|
|
151
177
|
```
|
|
152
178
|
|
|
153
179
|
All reversible. Your memories aren't locked in.
|
package/docs/releasing.md
CHANGED
|
@@ -5,9 +5,9 @@ Flair publishes eight workspace packages to npm under `@tpsdev-ai/*`. Releases a
|
|
|
5
5
|
(no `NPM_TOKEN` lives anywhere) and submits each package to npm's **staging** area.
|
|
6
6
|
A maintainer then approves the staged tarballs on npmjs.com with 2FA to make them live.
|
|
7
7
|
|
|
8
|
-
> `flair-bench` is version-bumped and tagged in lockstep with the other 7,
|
|
9
|
-
>
|
|
10
|
-
>
|
|
8
|
+
> `flair-bench` is version-bumped and tagged in lockstep with the other 7, and stages in
|
|
9
|
+
> its own step in CI for [historical reasons](#flair-bench-bootstrap-one-time-done). That
|
|
10
|
+
> step is no longer allowed to fail: all eight packages must stage for a release to pass.
|
|
11
11
|
|
|
12
12
|
```
|
|
13
13
|
merge release PR ──▶ push tag v0.11.0 ──▶ CI stages all packages ──▶ npm staging
|
|
@@ -29,13 +29,39 @@ the maintainer's 2FA approval.
|
|
|
29
29
|
### Phase 1 — open the release PR
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
# promote ## Unreleased to the new version in CHANGELOG.md first, then:
|
|
33
32
|
./scripts/release.sh 0.11.0
|
|
34
33
|
```
|
|
35
34
|
|
|
36
|
-
This bumps every workspace package to the version, aligns
|
|
37
|
-
`bun.lock`, builds, tests, and opens a `release: v0.11.0` PR.
|
|
38
|
-
(CI green + K&S approval) the same as any other PR.
|
|
35
|
+
This assembles the changelog, bumps every workspace package to the version, aligns
|
|
36
|
+
internal deps, refreshes `bun.lock`, builds, tests, and opens a `release: v0.11.0` PR.
|
|
37
|
+
Review and merge it (CI green + K&S approval) the same as any other PR.
|
|
38
|
+
|
|
39
|
+
**Nothing about the version is bumped by hand.** The version is declared outside
|
|
40
|
+
`package.json` too — `packages/flair-bench/src/version.ts` holds it as a `TOOL_VERSION`
|
|
41
|
+
constant — and `release.sh` bumps every such site. It checks them *before* creating the
|
|
42
|
+
branch, so an out-of-sync tree aborts while nothing has been touched, and again after the
|
|
43
|
+
bump so a missed site can't be committed. The same check runs in CI
|
|
44
|
+
(`node scripts/check-version-sync.mjs`) and fails on any file outside the known set that
|
|
45
|
+
declares the release version, so a new version-bearing file is caught on the PR that adds
|
|
46
|
+
it. If you ever find yourself editing a version constant by hand during a release, that is
|
|
47
|
+
a bug in the script — add the file to `SOURCE_VERSION_FILES` in
|
|
48
|
+
`scripts/check-version-sync.mjs` and to the `git add` list in `scripts/release.sh`.
|
|
49
|
+
|
|
50
|
+
**The changelog is assembled, not hand-promoted.** Entries land during development as one
|
|
51
|
+
file per change under `.changelog/unreleased/` (flair#835 — a shared `[Unreleased]` block
|
|
52
|
+
conflicted on every concurrent PR, and resolving a conflict dismisses approvals). The
|
|
53
|
+
release script runs:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
node scripts/changelog-fragments.mjs promote 0.11.0
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
which writes a `## [0.11.0] - <date>` section from the fragments — Keep a Changelog category
|
|
60
|
+
order, filename order within a category, entry bodies copied verbatim — and deletes the
|
|
61
|
+
fragment files. Released history above it is not touched. It **refuses** to run when the
|
|
62
|
+
fragment directory is empty (nothing to release) or when someone hand-wrote an entry into
|
|
63
|
+
`## [Unreleased]` that the step would otherwise silently overwrite. Preview any time with
|
|
64
|
+
`node scripts/changelog-fragments.mjs render`.
|
|
39
65
|
|
|
40
66
|
### Phase 2 — tag the release
|
|
41
67
|
|
|
@@ -51,9 +77,10 @@ workflow, which:
|
|
|
51
77
|
|
|
52
78
|
1. Resolves the version from the tag and validates it as semver.
|
|
53
79
|
2. Verifies the tagged commit is an ancestor of `main` (a tag can't ship un-merged code).
|
|
54
|
-
3. Verifies all
|
|
80
|
+
3. Verifies all 8 `package.json` files are at that version.
|
|
55
81
|
4. Builds every package.
|
|
56
|
-
5. Runs `npm stage publish` for each package in dependency order (flair-client first)
|
|
82
|
+
5. Runs `npm stage publish` for each package in dependency order (flair-client first),
|
|
83
|
+
then `flair-bench` in its own step. Any one of the eight failing fails the release.
|
|
57
84
|
|
|
58
85
|
It authenticates via OIDC — no secrets, and it does **not** create or move any tag (the
|
|
59
86
|
tag you pushed is the trigger). Watch the run; when it's green, the packages are staged
|
|
@@ -66,7 +93,8 @@ by `scripts/changelog-extract.mjs`). It is idempotent: re-running the workflow o
|
|
|
66
93
|
re-pushing the tag updates the existing release rather than failing. The GitHub release
|
|
67
94
|
documents the tagged commit immediately; it does not wait on the npm 2FA gate. If the
|
|
68
95
|
CHANGELOG has no section for the version, this job fails loudly rather than cutting an
|
|
69
|
-
empty release —
|
|
96
|
+
empty release — which is why phase 1's fragment assembly refuses to produce an empty
|
|
97
|
+
section rather than letting the failure surface here, after the tag is already pushed.
|
|
70
98
|
|
|
71
99
|
> `workflow_dispatch` with a `version` input remains as a manual fallback (needs
|
|
72
100
|
> `Actions: write`), but the tag push is the normal path.
|
|
@@ -82,10 +110,9 @@ npm stage view <stage-id> # inspect one
|
|
|
82
110
|
npm stage approve <stage-id> # 2FA prompt; package goes live
|
|
83
111
|
```
|
|
84
112
|
|
|
85
|
-
There are
|
|
113
|
+
There are eight lockstep-staged packages, so eight approvals (the web UI lists them on
|
|
86
114
|
one page). Approve in dependency order if installing immediately — flair-client before
|
|
87
|
-
its dependents — though staging does not itself resolve dependencies.
|
|
88
|
-
stages separately and only appears here once its bootstrap (below) is done.
|
|
115
|
+
its dependents — though staging does not itself resolve dependencies.
|
|
89
116
|
|
|
90
117
|
Verify when done:
|
|
91
118
|
|
|
@@ -99,7 +126,7 @@ These are configured once and reused for every release.
|
|
|
99
126
|
|
|
100
127
|
### npm trusted publisher (per package)
|
|
101
128
|
|
|
102
|
-
For **each** of the
|
|
129
|
+
For **each** of the eight packages, on npmjs.com → the package → **Settings → Trusted
|
|
103
130
|
Publisher → Add**:
|
|
104
131
|
|
|
105
132
|
| Field | Value |
|
|
@@ -116,32 +143,39 @@ CI/OIDC identity from publishing anything live directly — the only path to liv
|
|
|
116
143
|
human 2FA approval of a staged package.
|
|
117
144
|
|
|
118
145
|
Packages: `flair-client`, `flair-mcp`, `flair`, `openclaw-flair`, `pi-flair`,
|
|
119
|
-
`n8n-nodes-flair`, `langgraph-flair`.
|
|
146
|
+
`n8n-nodes-flair`, `langgraph-flair`, `flair-bench`.
|
|
120
147
|
|
|
121
148
|
> A package must already exist on npm before a trusted publisher can be added — all
|
|
122
|
-
>
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
`
|
|
131
|
-
(`
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
149
|
+
> eight already do. This account-level config can only be done by an npm org owner.
|
|
150
|
+
|
|
151
|
+
### `flair-bench` bootstrap (one-time, done)
|
|
152
|
+
|
|
153
|
+
**Nothing to do here.** This section is kept because the next brand-new package added to
|
|
154
|
+
the release set will hit the same wall, and because it explains why `flair-bench` still
|
|
155
|
+
stages in its own workflow step.
|
|
156
|
+
|
|
157
|
+
`flair-bench` (added 2026-07-12, flair#702) was wired into the version-bump/tag flow
|
|
158
|
+
(`scripts/release.sh`, `release-publish.yml`'s version-check) alongside the other 7 before
|
|
159
|
+
it existed on npm at all. That is a chicken-and-egg: `npm stage publish` categorically
|
|
160
|
+
requires the package to already exist on the registry (`npm help stage`: "Package must
|
|
161
|
+
exist"), and a Trusted Publisher can only be registered for a package that already exists.
|
|
162
|
+
So the workflow gave it a dedicated "Stage-publish flair-bench" step marked
|
|
163
|
+
`continue-on-error: true`, letting the expected failure pass without blocking the other 7,
|
|
164
|
+
and an npm org owner broke the cycle once:
|
|
165
|
+
|
|
166
|
+
1. One normal (non-staged) `npm publish --access public` from a machine logged into npm
|
|
167
|
+
with 2FA, to create the package on the registry. Any valid semver works — the next
|
|
168
|
+
lockstep release bumps it to match the other 7 automatically.
|
|
169
|
+
2. Add its Trusted Publisher using the same table as the other packages above.
|
|
170
|
+
|
|
171
|
+
Both are done, and the step staged `@tpsdev-ai/flair-bench` successfully at v0.30.0, so
|
|
172
|
+
`continue-on-error` has been **removed**: a flair-bench staging failure now fails the
|
|
173
|
+
release like any other package's.
|
|
174
|
+
|
|
175
|
+
> Why it mattered to go back and remove it: `continue-on-error: true` makes a step report
|
|
176
|
+
> `conclusion: success` even when it failed. While it was set, a green run was not evidence
|
|
177
|
+
> that flair-bench had staged — the only way to know was to read the raw log. A justified
|
|
178
|
+
> exception outlives the condition that justified it unless someone returns for it.
|
|
145
179
|
|
|
146
180
|
### GitHub `release` environment
|
|
147
181
|
|