@fml-inc/fml 0.7.0 → 0.8.0-rc.2

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.
Files changed (45) hide show
  1. package/.claude-plugin/plugin.json +2 -4
  2. package/README.md +323 -79
  3. package/agent-assets/fml/SKILL.md +180 -0
  4. package/bin/fml +4 -18
  5. package/bin/hook-handler +7 -0
  6. package/bin/mcp-server +4 -18
  7. package/bin/observer +6 -0
  8. package/dist/chunk-3KISRT57.js +140 -0
  9. package/dist/chunk-56TPYMNK.js +4657 -0
  10. package/dist/chunk-7V7G7NVF.js +142 -0
  11. package/dist/chunk-A6HAEVJX.js +1606 -0
  12. package/dist/chunk-DZKYW327.js +1037 -0
  13. package/dist/chunk-ENW2GJNO.js +109 -0
  14. package/dist/{chunk-PZ5AY32C.js → chunk-MLKGABMK.js} +0 -1
  15. package/dist/{chunk-PTUZMKSN.js → chunk-R45CWWZO.js} +34 -23
  16. package/dist/chunk-WZLLO563.js +953 -0
  17. package/dist/chunk-YSU5CS2V.js +3331 -0
  18. package/dist/cli.js +7742 -1072
  19. package/dist/{esm-2EUDFZWP.js → esm-4YKLKFRX.js} +546 -741
  20. package/dist/hook-handler.js +440 -0
  21. package/dist/mcp/server.js +112 -98
  22. package/dist/observer-server.js +1566 -0
  23. package/dist/sync-cycle.js +31 -0
  24. package/dist/{token-store-3IQSLOTQ.js → token-store-BT5THIAJ.js} +10 -3
  25. package/hooks/hooks.json +290 -0
  26. package/package.json +24 -27
  27. package/dist/chunk-PTUZMKSN.js.map +0 -1
  28. package/dist/chunk-PZ5AY32C.js.map +0 -1
  29. package/dist/chunk-S4TJNLEN.js +0 -61
  30. package/dist/chunk-S4TJNLEN.js.map +0 -1
  31. package/dist/chunk-VV4JHH4H.js +0 -437
  32. package/dist/chunk-VV4JHH4H.js.map +0 -1
  33. package/dist/chunk-YH5ROR7G.js +0 -69
  34. package/dist/chunk-YH5ROR7G.js.map +0 -1
  35. package/dist/cli.js.map +0 -1
  36. package/dist/daemon-MSLDHLMH.js +0 -21
  37. package/dist/daemon-MSLDHLMH.js.map +0 -1
  38. package/dist/daemon-utils-OODBIYB7.js +0 -10
  39. package/dist/daemon-utils-OODBIYB7.js.map +0 -1
  40. package/dist/esm-2EUDFZWP.js.map +0 -1
  41. package/dist/mcp/server.js.map +0 -1
  42. package/dist/postinstall.js +0 -16
  43. package/dist/postinstall.js.map +0 -1
  44. package/dist/token-store-3IQSLOTQ.js.map +0 -1
  45. package/scripts/postinstall.cjs +0 -25
@@ -1,13 +1,11 @@
1
1
  {
2
2
  "name": "fml",
3
- "version": "0.7.0",
3
+ "version": "0.8.0-rc.2",
4
4
  "description": "FML agent tools for Claude Code",
5
5
  "mcpServers": {
6
6
  "fml": {
7
7
  "command": "node",
8
- "args": [
9
- "${CLAUDE_PLUGIN_ROOT}/bin/mcp-server"
10
- ]
8
+ "args": ["${CLAUDE_PLUGIN_ROOT}/bin/mcp-server"]
11
9
  }
12
10
  }
13
11
  }
package/README.md CHANGED
@@ -1,61 +1,266 @@
1
- # FML
1
+ # FML CLI
2
2
 
3
- Agent tools for AI coding assistants. Installs as a [Claude Code plugin](https://docs.anthropic.com/en/docs/claude-code/plugins) with MCP tools for session analytics, cost tracking, integrations, and team workflows — powered by [Panopticon](https://github.com/fml-inc/panopticon) for local data collection.
3
+ `@fml-inc/fml` is the single published FML command-line package. It provides
4
+ the `fml` command, account and organization authentication, agent MCP
5
+ integration, cloud-backed product commands, and raw artifact sync.
6
+
7
+ Panopticon is an internal workspace engine under `packages/panopticon`. Its
8
+ raw-sync implementation is bundled into this package at build time; users do
9
+ not install or run a second Panopticon package.
4
10
 
5
11
  ## Install
6
12
 
13
+ Node.js 22.15 or newer and npm are required.
14
+
15
+ On macOS, Linux, and compatible Bash environments, install with:
16
+
7
17
  ```bash
8
- npm install -g @fml-inc/fml
18
+ curl -fsSL https://fml.inc/install.sh | bash
9
19
  ```
10
20
 
11
- This installs the plugin, registers hooks and MCP tools in Claude Code, and bootstraps Panopticon for local data collection. Start a new session to activate.
12
-
13
- Then sign in:
21
+ For Windows or manual installation, run:
14
22
 
15
23
  ```bash
16
- fml login
24
+ npm install --global @fml-inc/fml
25
+ fml setup
17
26
  ```
18
27
 
19
- ## For LLM agents
28
+ Run `fml update` to upgrade the global package with npm. Stable releases stay
29
+ on npm's `latest` channel; prerelease versions stay on `next`.
20
30
 
21
- Setting up FML from inside a coding-agent sandbox (Claude Code, Codex, Gemini CLI, etc.)? Paste this to your agent:
31
+ Installing the package does not change agent configuration. Run `fml setup`
32
+ to register every supported FML agent integration, sign in when needed, and
33
+ restart the observer. It installs the agent-native FML skill, configures the
34
+ FML MCP server, and registers capture-only lifecycle hooks for supported
35
+ agents. Invoke the skill as `/fml review` in Claude, Gemini, or Grok, and as
36
+ `$fml review` in Codex. Review runs inside the agent from the packaged skill;
37
+ it is not an `fml review` CLI command. Start a new agent session after setup so
38
+ it picks up the integration. FML pre-approves only the isolated command hooks
39
+ it installs for Codex; use `/hooks` to review or disable them.
22
40
 
23
- ```
24
- Follow the installation instructions here: https://github.com/fml-inc/observe/blob/main/docs/agent_installation_guide.md
41
+ The Claude plugin is MCP-only. FML installs the workflow through each host's
42
+ native skill directory so it keeps the bare `fml` name without a second,
43
+ plugin-namespaced skill.
44
+
45
+ For a coding agent operating in a sandbox, use the
46
+ [agent installation guide](./docs/agent_installation_guide.md).
47
+
48
+ ## Upgrading from standalone Panopticon
49
+
50
+ Earlier releases shipped as a separate `@fml-inc/panopticon` package that
51
+ installed its own Claude plugin, agent hooks, MCP server, OpenTelemetry
52
+ settings, and shell environment. `fml install` does not migrate that install.
53
+ Retire it first, from the machine that has it, before installing FML:
54
+
55
+ ```bash
56
+ panopticon uninstall --purge
25
57
  ```
26
58
 
27
- The guide covers: `npm install -g @fml-inc/fml` → `fml install` → `fml login --device` (the agent relays the verification URL to you, you paste the code back) → `fml doctor`. No browser, no `gh` CLI, no manual shell-profile edits needed.
59
+ `panopticon uninstall --purge` stops the standalone daemon and removes its
60
+ plugin, hooks, MCP registrations, shell block, and generated data directory.
61
+ Then follow the [Install](#install) steps above for a clean setup. If the old
62
+ `panopticon` command is already gone, reinstall `@fml-inc/panopticon` just to
63
+ run its uninstall, or clean up by hand: remove the `# >>> panopticon >>>` block
64
+ from your shell profile, delete the data directory (macOS:
65
+ `~/Library/Application Support/panopticon`; Linux: `~/.local/share/panopticon`;
66
+ Windows: `%APPDATA%\panopticon`), and remove any leftover `panopticon` entries
67
+ from the Claude plugin registration (`~/.claude/settings.json` and
68
+ `~/.claude/plugins/`), agent hook configs (`~/.codex/config.toml`,
69
+ `~/.codex/hooks.json`, `~/.gemini/settings.json`, `~/.grok/hooks/`), and MCP
70
+ server registrations in those same agent config files.
71
+
72
+ ## Raw artifact sync
73
+
74
+ Sync uploads original, file-backed agent artifacts to FML. It does not parse
75
+ them into local session, message, tool-call, or scanner tables. Server-side
76
+ scanners own parsing and projections.
77
+
78
+ Discovery covers supported local stores across Claude Code, Codex, Gemini,
79
+ Grok, Cursor, Pi, Copilot CLI, and Factory Droid, including archived Codex
80
+ sessions. Availability depends on which harnesses have written artifacts on
81
+ the machine.
82
+
83
+ Sync has one persistent setting: enabled or disabled. It defaults to enabled.
84
+ The backend environment, login, and selected organization determine the upload
85
+ destination; there is no user-configurable sync-target list.
28
86
 
29
- ## What it does
87
+ ```bash
88
+ fml sync # Discover and drain pending raw artifacts
89
+ fml sync --dry-run # Show what would be discovered without changing the queue
90
+ fml sync status # Show enabled state, queue counts, and byte watermarks
91
+ fml sync disable # Stop discovery and upload
92
+ fml sync enable # Allow discovery and upload again
93
+ fml sync reset # Clear watermarks and replay every local artifact from byte zero
94
+ fml start # Start the observer and continuously run enabled raw sync
95
+ fml restart # Stop and start the observer
96
+ fml stop # Stop the observer and disable raw sync
97
+ ```
30
98
 
31
- **Local observability** — Panopticon captures OpenTelemetry signals, hook events, session files, and API traffic from Claude Code, Gemini CLI, and Codex CLI into a local SQLite database.
99
+ `fml sync reset` preserves the enabled/disabled setting and source files. It
100
+ clears local upload progress and gives tracked artifacts fresh generations, so
101
+ the next enabled `fml sync` performs a full replay. Reset refuses to race an
102
+ active sync.
103
+
104
+ For automation, the sync commands support `--json`. `fml start` enables raw
105
+ sync and launches a detached observer with a loopback-only HTTP endpoint. The
106
+ observer runs sync immediately, retries in the background, and follows later
107
+ `fml env` and `fml org` changes. `fml sync disable` pauses only raw discovery
108
+ and upload. Capture-only hooks continue writing to their durable local outbox
109
+ and uploading in the background. `fml stop` disables raw sync, records an
110
+ explicit hook-capture pause, and stops the complete observer runtime. Either
111
+ `fml start` or `fml sync enable` clears that pause. A crash or reboot does not
112
+ pause capture: handler inbox files remain durable until the observer returns.
113
+
114
+ The observer keeps a SQLite database for runtime bookkeeping and the
115
+ durable hook outbox. It is operational state, not a local copy of session,
116
+ message, scanner, or analytics tables. Hermes discovery and sync remain
117
+ deferred.
118
+
119
+ The database is `panopticon.db` under FML's platform-native operational-state
120
+ root:
121
+
122
+ | Platform | Account/configuration (`FML_DATA_DIR`) | Operational database |
123
+ | -------- | -------------------------------------- | ----------------------------------------------------- |
124
+ | macOS | `~/Library/Application Support/fml` | `~/Library/Application Support/fml/panopticon.db` |
125
+ | Linux | `${XDG_DATA_HOME:-~/.local/share}/fml` | `${XDG_STATE_HOME:-~/.local/state}/fml/panopticon.db` |
126
+ | Windows | `%APPDATA%\fml` | `%LOCALAPPDATA%\fml\panopticon.db` |
127
+
128
+ The cutover is forward-only: the observer starts with a clean database at the
129
+ new path and does not migrate or delete the former
130
+ `~/.fml/panopticon/observer.db`. `fml start` reports that retained path whenever
131
+ the file still exists; when replacing a live legacy observer, it also reports
132
+ the old observer's pending row count. The PID state, lease/lock, endpoint,
133
+ auth-token files, hook inbox, and raw-sync watermarks remain under the
134
+ separately configurable observer directory.
135
+
136
+ Use `FML_STATE_DIR` to relocate the operational database and `FML_DATA_DIR` to
137
+ relocate account and environment configuration. For compatibility, an explicit
138
+ `FML_DATA_DIR` also relocates the database when `FML_STATE_DIR` is absent. It
139
+ does not relocate logs or observer coordination state: those retain their
140
+ platform defaults unless `FML_LOG_DIR` or an observer override is set.
141
+ `FML_OBSERVER_DIR` directly relocates observer coordination state;
142
+ `PANOPTICON_HOME` is a legacy alias for that directory and `FML_HOME` is a
143
+ legacy parent whose `panopticon` child is used. These observer-only aliases do
144
+ not relocate the database or account configuration. Because that pattern used
145
+ to isolate the pre-cutover database as well, `fml start` and the observer warn
146
+ at startup when an observer-only alias is set without `FML_STATE_DIR` or
147
+ `FML_DATA_DIR`; set one of those to choose the database root explicitly.
148
+
149
+ Every explicit FML directory override must be absolute; relative values are
150
+ rejected so processes launched from different working directories cannot
151
+ silently select different state. Relative XDG and Windows shell-directory
152
+ variables are ignored in favor of the platform fallback.
153
+
154
+ The filesystems containing `FML_STATE_DIR` and `FML_OBSERVER_DIR` must support
155
+ same-directory hard links. FML uses that atomic primitive to publish complete
156
+ observer lease records without exposing a partially written database lock;
157
+ standard APFS, ext4, and NTFS volumes support it.
158
+
159
+ For multiple fully isolated FML instances, configure absolute, dedicated
160
+ `FML_DATA_DIR`, `FML_LOG_DIR`, and `FML_OBSERVER_DIR` roots per instance.
161
+ `FML_DATA_DIR` also isolates the database unless a separate `FML_STATE_DIR` is
162
+ set. Configuring a distinct `FML_OBSERVER_PORT` is also recommended. A
163
+ database-scoped runtime lease rejects a second observer that resolves to the
164
+ same `panopticon.db`; give that instance a different data or state root and
165
+ start it again.
166
+
167
+ ## Hook capture
168
+
169
+ FML installs capture-only hooks for Claude Code, Codex, Gemini CLI, and Grok
170
+ CLI. It also configures direct MCP entries for Codex, Gemini, Grok, and Claude
171
+ Desktop. The hook handler reads the agent's JSON event, first commits an
172
+ owner-only per-delivery file, then sends it only to the authenticated loopback
173
+ observer, and always returns an empty JSON object. It does not make permission
174
+ decisions, inject context, or contact FML directly.
175
+
176
+ The observer commits each event to SQLite before removing its handler-side
177
+ delivery file. Files left by a stopped, restarting, busy, or unavailable
178
+ observer are replayed with the same sync ID, so a timeout cannot create a
179
+ duplicate or silently drop the event. A separate uploader sends stable,
180
+ idempotent batches through `/v2/sync` to the selected FML environment and
181
+ account, then removes local rows only after the server acknowledges them.
182
+ Repository authorization is evaluated per row across every organization the
183
+ account can access; hook delivery does not depend on the currently selected
184
+ organization. `fml status` reports both the handler inbox and SQLite outbox.
185
+
186
+ Each capture with known login state is durably bound to its exact FML URL,
187
+ and stable account identity; switching environments or accounts cannot upload
188
+ or acknowledge another destination's rows. Captures made while logged out
189
+ remain unbound until the first authenticated destination atomically claims that
190
+ backlog.
191
+
192
+ The handler-side inbox is a short-lived durability bridge for times when the
193
+ observer is stopped or unavailable. It is bounded independently from the
194
+ SQLite spool: by default it accepts at most 512 MiB or 10,000 delivery files,
195
+ whichever is reached first. At a limit it preserves older committed files,
196
+ refuses the newest inbox write, and still fails open for the invoking agent; a
197
+ running observer can still accept that event directly. `fml status` reports
198
+ the active limits and cumulative capacity refusals.
199
+
200
+ Set `FML_HOOK_INBOX_MAX_BYTES` and `FML_HOOK_INBOX_MAX_ENTRIES` in the coding
201
+ agent's environment to change these limits. Bytes accept the same `B`, `KiB`,
202
+ `MiB`, and `GiB` suffixes described below; entries are positive integers. An
203
+ explicit `unbounded` opts out of either limit. These settings affect only the
204
+ per-delivery file inbox and do not change normal SQLite spool retention.
205
+
206
+ The hook spool is unbounded by default. To bound it, set
207
+ `FML_HOOK_SPOOL_MAX_BYTES` when starting the observer:
32
208
 
33
- **MCP tools for your agent** — Once installed, Claude Code gets tools to query your sessions, costs, activity, and connected integrations directly in conversation.
209
+ ```bash
210
+ FML_HOOK_SPOOL_MAX_BYTES=512MiB fml start
211
+ ```
34
212
 
35
- **Cloud sync** — Optionally sync local data to the FML dashboard for team-wide visibility, config snapshots, and automations.
213
+ The value is a positive integer in bytes with an optional `B`, `KiB`, `MiB`,
214
+ or `GiB` suffix. Unset it, or set it to `unbounded`, to retain the full spool
215
+ without a size limit. Invalid values (including `0`) stop observer startup
216
+ instead of silently disabling the limit. Restart a running observer after
217
+ changing the setting.
218
+
219
+ This is a logical-content limit: it counts the UTF-8 bytes retained in hook
220
+ fields and their destination or rejection metadata across pending and
221
+ quarantined rows, not SQLite page, index, or WAL overhead. When the limit is
222
+ exceeded, the observer evicts the oldest quarantined rows first and then the
223
+ oldest pending rows. It never fails a hook invocation merely because the spool
224
+ is full. `fml status` reports current logical bytes, the configured maximum,
225
+ cumulative eviction counts and bytes, and the last eviction time.
226
+
227
+ Terminally rejected rows are retained for 30 days by default, independently
228
+ of the pending spool's unbounded default. Set
229
+ `FML_HOOK_QUARANTINE_MAX_AGE_DAYS` to a positive integer to change that window,
230
+ or to `unbounded` to retain quarantine rows until the byte bound evicts them.
231
+ Expired quarantine rows contribute to the same persisted eviction counters.
232
+ Retryable pending rows are never removed by this age policy.
233
+
234
+ The spool retains complete hook payloads and extracted fields, which can
235
+ include prompts, commands, file paths, plans, and tool output. FML-created
236
+ directories request owner-only permissions, and the SQLite database and
237
+ sidecars are tightened to owner-only modes on platforms that support POSIX
238
+ modes. An existing caller-supplied state directory retains its directory mode.
36
239
 
37
240
  ## MCP tools
38
241
 
39
- These tools are available to Claude Code via the plugin:
40
-
41
- | Tool | Description |
42
- |------|-------------|
43
- | `get_engineering_activity` | Activity summary — sessions, prompts, tools, costs |
44
- | `list_engineering_sessions` | List recent sessions with stats |
45
- | `search_engineering_sessions` | Search across all sessions |
46
- | `get_session_timeline` | Messages and tool calls for a session |
47
- | `get_session_turns` | Per-turn token usage for a session |
48
- | `get_ai_spending` | Token usage and cost breakdowns |
49
- | `whoami` | Current auth and org status |
50
- | `fml_list_integrations` | Connected integrations (Slack, GitHub, Linear, Sentry, etc.) |
51
- | `fml_query_*` | Query connected integrations directly |
52
- | `fml_list_messages` | Conversation messages |
53
- | `fml_search_analysis` | Search codebase analysis results |
54
- | `fml_run_analysis_workflow` | Run deep analysis workflows |
55
- | `fml_list_skills` | Browse and load skills |
56
- | `list_repo_configs` | Team config snapshots |
57
-
58
- For agents or scripts that need backend tools not exposed as dedicated MCP tools yet, use the dynamic CLI catalog:
242
+ The MCP server exposes FML tools for session analytics, cost tracking,
243
+ integrations, team workflows, and account context, including:
244
+
245
+ | Tool | Description |
246
+ | ----------------------------- | ----------------------------------------------------------- |
247
+ | `get_engineering_activity` | Activity summary across sessions, prompts, tools, and costs |
248
+ | `list_engineering_sessions` | List recent sessions with stats |
249
+ | `search_engineering_sessions` | Search across sessions |
250
+ | `get_session_timeline` | Messages and tool calls for a session |
251
+ | `get_session_turns` | Per-turn token usage for a session |
252
+ | `get_ai_spending` | Token usage and cost breakdowns |
253
+ | `whoami` | Current auth and organization status |
254
+ | `fml_list_integrations` | Connected integrations |
255
+ | `fml_query_*` | Query connected integrations |
256
+ | `fml_list_messages` | Conversation messages |
257
+ | `fml_search_analysis` | Search codebase analysis results |
258
+ | `fml_run_analysis_workflow` | Run analysis workflows |
259
+ | `fml_list_skills` | Browse and load skills |
260
+ | `list_repo_configs` | Team configuration snapshots |
261
+
262
+ For backend tools not yet exposed as dedicated MCP tools, use the dynamic
263
+ catalog:
59
264
 
60
265
  ```bash
61
266
  fml tools list --json
@@ -63,62 +268,101 @@ fml tools describe <tool-name> --json
63
268
  fml tools call <tool-name> --args '{"key":"value"}'
64
269
  ```
65
270
 
66
- ## CLI
67
-
68
- ```
69
- fml install Register plugin, hooks, and daemons
70
- fml uninstall Remove plugin and hooks
71
- --target <t> Target: claude, gemini, codex, claude-desktop, all
72
- --purge Also remove all data, logs, and auth tokens
73
- fml update Update to the latest version
74
-
75
- fml login Sign in to your FML account
76
- fml logout Sign out and clear credentials
77
- fml org [slug] Show or select organization
78
- fml status Show auth and daemon status
79
- fml doctor Check configuration and connectivity
80
-
81
- fml open Open FML dashboard in browser
82
- fml start Start local collection and sync
83
- fml stop Stop local collection and sync
84
-
85
- fml tools List backend tools from the dynamic catalog
86
- fml tools list List backend tools from the dynamic catalog
87
- fml tools describe <n> Show a backend tool schema
88
- fml tools call <n> Invoke a backend tool with JSON args
89
-
90
- fml activity Activity summary
91
- --since <duration> Time window (e.g. "24h", "7d")
271
+ ## CLI overview
272
+
273
+ ```text
274
+ fml setup Install integrations, sign in if needed, and start FML
275
+ fml install Register FML agent integrations and the MCP server
276
+ fml uninstall Remove agent integration; add --purge to remove local state
277
+ fml update Update @fml-inc/fml with npm (stable: latest; prerelease: next)
278
+
279
+ fml start Start the local observer and continuous raw sync
280
+ fml restart Stop and start the local observer
281
+ fml stop Stop the local observer and disable raw sync
282
+
283
+ fml login Sign in to FML
284
+ fml logout Clear stored credentials
285
+ fml org [slug] Show or select an organization
286
+ fml env [name-or-url] Show or select a backend environment
287
+ fml status Show auth, environment, and raw-sync status
288
+ fml doctor Check auth, environment, organization, raw sync, and API access
289
+ fml open Open the FML dashboard
290
+
291
+ fml sync Upload raw local artifacts
292
+ fml sync enable Enable raw artifact sync
293
+ fml sync disable Disable raw artifact sync
294
+ fml sync status Show queue counts and byte watermarks
295
+ fml sync reset Replay all raw artifacts from byte zero
296
+
297
+ fml tools Browse and invoke backend tools
298
+ fml activity Show an activity summary
92
299
  fml sessions List recent sessions
93
- fml timeline <id> Events for a session
94
- fml spending Token usage and cost breakdown
95
- fml search <query> Search across sessions
96
-
97
- fml sync setup Configure sync targets
98
- fml sync list List sync targets
99
- fml sync add <n> <url> Add a sync target
100
- fml sync remove <name> Remove a sync target
101
- fml sync status Show sync status
102
- fml sync reset [name] Reset sync watermarks
300
+ fml timeline <id> Show events for a session
301
+ fml spending Show token usage and cost breakdowns
302
+ fml search <query> Search sessions
103
303
  ```
104
304
 
305
+ Run `fml --help` or `fml commands` for the complete command inventory.
306
+
105
307
  ## Development
106
308
 
309
+ Run from the repository root:
310
+
107
311
  ```bash
108
- pnpm install # Install dependencies
109
- pnpm dev # Watch mode (tsup)
110
- pnpm test # Run tests (Vitest)
111
- pnpm type-check # Type check
312
+ pnpm install
313
+ pnpm --filter @fml-inc/fml type-check
314
+ pnpm --filter @fml-inc/fml test
315
+ pnpm --filter @fml-inc/fml build
112
316
  ```
113
317
 
114
- To test the full install flow:
318
+ Build, pack, and install the same artifact that will be published:
115
319
 
116
320
  ```bash
117
- pnpm build && pnpm pack
118
- npm install -g ./fml-inc-fml-*.tgz
321
+ pnpm --filter @fml-inc/fml pack:local
322
+ pnpm add --global ./apps/cli/fml-inc-fml-*.tgz
323
+ fml --version
119
324
  fml install
120
325
  ```
121
326
 
327
+ The packed manifest must not contain runtime dependencies on
328
+ `@fml/panopticon` or `@fml/agent-targets`; both private workspace packages are
329
+ bundled into the CLI.
330
+
331
+ ## Release
332
+
333
+ The [FML CLI release workflow](../../.github/workflows/publish-fml-cli.yml)
334
+ publishes the exact package that passes the packed-install smoke test. Create a
335
+ tag named `fml-v<semver>` on a commit reachable from `main`, then push the tag:
336
+
337
+ ```bash
338
+ git tag -a fml-v0.8.0 -m "Release FML CLI 0.8.0"
339
+ git push origin fml-v0.8.0
340
+ ```
341
+
342
+ Stable versions use npm's default `latest` tag. SemVer prereleases such as
343
+ `fml-v0.9.0-beta.1` publish under `next`. Each release must advance the version
344
+ currently assigned to its npm channel; the workflow rejects stable versions
345
+ that do not advance `latest` and prereleases that do not advance `next`.
346
+ Release tags may not contain SemVer build metadata. Keep
347
+ `apps/cli/package.json` at `0.0.0-dev` on `main`; the workflow stamps the
348
+ release version before building.
349
+
350
+ The `@fml-inc/fml` package must have one npm trusted publisher configured with
351
+ these exact values:
352
+
353
+ - Provider: GitHub Actions
354
+ - Organization: `fml-inc`
355
+ - Repository: `fml`
356
+ - Workflow: `publish-fml-cli.yml`
357
+ - Environment: `npm`
358
+ - Allowed action: `npm publish`
359
+
360
+ The GitHub `npm` environment should allow only `fml-v*` tags and may require a
361
+ reviewer. The publish job has no npm token, source checkout, dependency
362
+ installation, or build step; it receives only the smoke-tested tarball and its
363
+ checksum. npm provenance is disabled because the source repository is private,
364
+ while OIDC trusted publishing remains enabled.
365
+
122
366
  ## License
123
367
 
124
368
  Proprietary — see [LICENSE](LICENSE).
@@ -0,0 +1,180 @@
1
+ ---
2
+ name: fml
3
+ description: Route explicit FML requests to FML MCP tools, CLI operations, or the built-in branch and pull-request review workflow. Use when the user invokes /fml or $fml, explicitly asks to use FML, requests an FML command or tool, or asks for `fml review`. The `review` route is an agent workflow, never an `fml review` CLI command.
4
+ ---
5
+
6
+ <!-- fml-managed-agent-surface:v1 -->
7
+
8
+ # FML Agent Router
9
+
10
+ Use this skill as FML's agent-native command surface. Route a request to an
11
+ FML MCP tool, an actual `fml` CLI command, or an agent workflow defined here.
12
+
13
+ ## Invocation contract
14
+
15
+ Use the user text that activated this skill. Different hosts may preserve
16
+ trailing text in the original prompt, append an arguments annotation, or
17
+ deliver it immediately after activation. Treat that accompanying text as
18
+ `<command> [args...]`; do not depend on one host's invocation syntax or
19
+ argument-substitution behavior.
20
+
21
+ For an explicit skill invocation, parse the first trailing token as the
22
+ subcommand. For a natural-language invocation, infer a subcommand only from
23
+ the user's explicit FML request. With no subcommand, show concise help and do
24
+ not run a command merely to fill the response.
25
+
26
+ ## Routing rules
27
+
28
+ 1. Select `review` before doing CLI or MCP discovery. If the subcommand is
29
+ `review`, or the user explicitly asks for the FML review workflow, perform
30
+ the complete review workflow below in this agent session. `review` is not
31
+ an FML CLI subcommand. Never execute `fml review` or delegate the workflow
32
+ to the CLI.
33
+ 2. For structured read-only data, prefer a dedicated FML MCP tool when one is
34
+ available. Prefer the CLI for install, authentication, lifecycle, observer,
35
+ environment, and sync operations.
36
+ 3. If command coverage is unclear, run `fml commands`. For backend tools, run
37
+ `fml tools list --json` and `fml tools describe <name> --json`; do not guess
38
+ tool names or argument schemas.
39
+ 4. FML activity and history commands read data synced to the selected FML
40
+ organization. If the user explicitly asks for unsynced, machine-local
41
+ session data, explain that this command surface does not expose a local
42
+ analytics database.
43
+ 5. Apply the host's normal approval and safety rules to writes and destructive
44
+ actions. Never silently run `sync reset`, `uninstall --purge`, integration
45
+ writes, automation mutations, memory writes or deletes, or analysis runs.
46
+ 6. Summarize large structured results unless the user asks for raw output.
47
+
48
+ ## Common routes
49
+
50
+ - `review`: follow the complete pull-request review workflow below in the
51
+ current agent session.
52
+ - Install, auth, environment, observer, lifecycle, or sync: use the CLI command
53
+ discovered through `fml commands` or command help.
54
+ - Read-only activity, history, spending, configuration, integration, or
55
+ provenance: use the matching FML MCP tool by its live description, with a
56
+ CLI fallback when available.
57
+ - Backend tool list, description, or invocation: use `fml tools ...` and
58
+ describe unfamiliar tools before calling them.
59
+ - Automations, memory, analysis runs, integration writes, or other mutations:
60
+ discover the live schema, explain the change, and obtain any required
61
+ approval before invoking it.
62
+
63
+ If the preferred route is unavailable, use the listed fallback and say which
64
+ fallback was used.
65
+
66
+ ## CLI discovery
67
+
68
+ Use runtime discovery instead of relying on a static command inventory:
69
+
70
+ ```bash
71
+ fml commands
72
+ fml tools list --json
73
+ fml tools list --category integrations --json
74
+ fml tools describe <name> --json
75
+ fml tools call <name> --args '<json>'
76
+ fml tools call <name> --file <path>
77
+ ```
78
+
79
+ Prefer `--file` for multiline or nested JSON. Run `fml <command> --help` before
80
+ using an unfamiliar bespoke command.
81
+
82
+ ## Authentication and failures
83
+
84
+ - Use `fml doctor` to diagnose authentication, organization, observer, sync,
85
+ environment, and API connectivity.
86
+ - Use `fml login --device` when an interactive browser callback is unavailable.
87
+ - Never print or copy credential-store files or token values.
88
+ - Report the failed command and the relevant error. Do not retry indefinitely.
89
+
90
+ ## Pull-request review workflow
91
+
92
+ Apply this entire section for the `review` route.
93
+
94
+ ### 1. Establish the review scope
95
+
96
+ 1. Read repository instructions that govern the changed files.
97
+ 2. Determine the current branch and base ref. Prefer an explicitly supplied
98
+ base or PR base. Otherwise use the remote default from
99
+ `refs/remotes/origin/HEAD`, then fall back to a local `main` or `master`.
100
+ Do not fetch or mutate branches solely to perform the review.
101
+ 3. Inspect the branch and working-tree scope separately:
102
+
103
+ ```bash
104
+ git status --short
105
+ git diff --stat <base>...HEAD
106
+ git diff --find-renames <base>...HEAD
107
+ git log --oneline --decorate <base>..HEAD
108
+ git diff
109
+ git diff --cached
110
+ ```
111
+
112
+ 4. Read complete changed files and relevant callers, tests, schemas, or
113
+ configuration when the diff alone is insufficient.
114
+
115
+ State the chosen base and whether uncommitted changes are included. If no
116
+ reliable base can be determined, ask the user rather than inventing one.
117
+
118
+ ### 2. Review the code
119
+
120
+ Prioritize defects that could affect users or maintainers:
121
+
122
+ - correctness, edge cases, and error handling
123
+ - security, authorization, privacy, and secret handling
124
+ - data loss, unsafe migrations, and irreversible operations
125
+ - concurrency, retries, idempotency, and partial failure
126
+ - compatibility across supported platforms and agent targets
127
+ - public contracts, packaging, install/uninstall symmetry, and upgrade paths
128
+ - missing tests for meaningful behavior or regression risk
129
+
130
+ Do not report formatting preferences or speculative concerns as defects. Trace
131
+ the actual execution path and cite the smallest useful file and line location.
132
+ Each finding must explain the triggering conditions, concrete impact, and a
133
+ practical repair direction.
134
+
135
+ ### 3. Use FML context only for unresolved intent
136
+
137
+ Finish the code-based review before consulting FML. If a finding or design
138
+ question remains ambiguous, use read-only FML context:
139
+
140
+ - `fml_commit_context` for branch commits
141
+ - `fml_path_history` for the history of a changed path
142
+ - `fml_pr_context` when the pull-request number is known
143
+ - `search_engineering_sessions`, followed by `get_session_timeline`, for
144
+ relevant synced implementation sessions
145
+
146
+ CLI fallbacks are `fml search`, `fml sessions`, and `fml timeline`. If FML is
147
+ unavailable, unauthenticated, or has no matching data, note that briefly and
148
+ complete the review from repository evidence. Never use historical intent to
149
+ excuse a concrete defect in the current code.
150
+
151
+ Put any material provenance answer after the verdict under
152
+ `Follow-up: FML-sourced intent`, clearly separated from the findings.
153
+
154
+ ### 4. Report
155
+
156
+ Lead with findings, ordered by severity:
157
+
158
+ ```text
159
+ Findings
160
+
161
+ - [P1] Short imperative title — path/to/file.ts:42
162
+ Explain the triggering scenario, impact, and repair direction.
163
+
164
+ Questions / assumptions
165
+
166
+ - Only questions that materially affect the review.
167
+
168
+ Verdict
169
+
170
+ Request changes | Approve with comments | Approve
171
+
172
+ Follow-up: FML-sourced intent
173
+
174
+ - Include only if FML resolved a lingering question.
175
+ ```
176
+
177
+ Use `P0` for release-blocking or catastrophic risk, `P1` for serious defects,
178
+ `P2` for normal correctness or maintainability defects, and `P3` sparingly for
179
+ minor actionable issues. If there are no findings, say so explicitly and call
180
+ out any meaningful test or evidence gap in the verdict.