Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "fdeops",
"description": "Second brain for Forward Deployed Engineers. One @fde skill - enter at day one, mid-project, or mid-fire; it routes and does the phase work; engagement memory lands in .fde/ as you confirm judgment.",
"version": "3.11.0",
"version": "3.11.1",
"category": "productivity",
"tags": [
"community-managed"
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 3.11.1 — 2026-08-27

Adoption: one skill, and the CLI is never missing.

### Fixed
- **A skill-only install had no hands.** `npx skills add` copies the method but not the CLI, and the router's only fallback was `~/.claude/fdeops/fde.js` - absent on Cursor/Codex/anything that is not a Claude Code install - so the agent dropped to writing `.fde/` by hand and lost the dating, gates and `<private>` redaction the CLI enforces. It now reaches for `npx --yes fdeops <verb>` before any manual path; "CLI unavailable" means no Node or no network, not "not installed".
- **The advertised install pulled a contributor skill.** A bare `npx skills add suboss87/fdeops` also installs `testing-fieldbook`, which is for people working on this repo. The documented command is `--skill fde`, and a gate keeps it that way.

## 3.11.0 — 2026-08-27

One window over every client, without a second memory to maintain.
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ Nothing to install to see it on a fake client: `npx fdeops demo`.
```

```bash
npx skills add suboss87/fdeops # Cursor, Codex, skills-compatible hosts
npx skills add suboss87/fdeops --skill fde # Cursor, Codex, skills-compatible hosts
```

That is one skill, not a catalogue - `@fde` routes the whole method. The CLI needs no install either: the skill reaches for `npx fdeops` when `fde` is not on the PATH. (Drop `--skill fde` and you also get `testing-fieldbook`, which is for people contributing to this repo, not for field work.)

Claude Code additionally gets session hooks, so context arrives before you type. Everywhere else it is the same fieldbook, loaded when you ask.

**2. Bind once** in the client workspace:
Expand Down
16 changes: 16 additions & 0 deletions bin/check.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,22 @@ if (!readme.includes('fde-engagements') || !/fdeops.*init.*engagement/i.test(rea
fail('README must document fde-engagements + init flow')
} else ok('README engagement path')

// The contributor-only testing skill lives in .agents/skills/, so a bare
// `skills add` installs it too. The advertised command must name the one skill
// a field user wants.
for (const m of readme.match(/^.*npx skills add .*$/gm) || []) {
if (!m.includes('--skill fde')) {
fail(`README skills-add command must pin --skill fde: ${m.trim()}`)
}
}
ok('README skills install is one skill')

// A skill-only install has no fde on the PATH; the router must reach npx before
// falling back to writing memory by hand.
if (!read('skills/fde/SKILL.md').includes('npx --yes fdeops')) {
fail('skills/fde/SKILL.md must fall back to npx --yes fdeops when the CLI is not installed')
} else ok('SKILL.md npx CLI fallback')

if (!fs.existsSync(path.join(root, 'docs', 'USAGE.md'))) {
fail('docs/USAGE.md missing')
} else ok('docs/USAGE.md')
Expand Down
2 changes: 1 addition & 1 deletion mcp/fdeops-ingest/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fdeops-ingest-mcp",
"version": "3.11.0",
"version": "3.11.1",
"private": true,
"description": "Thin stdio MCP sink for FDEOps ingest (stage → propose → apply). Zero runtime dependencies.",
"bin": {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fdeops",
"version": "3.11.0",
"version": "3.11.1",
"description": "Field kit for engineers embedded in client work - a real CLI (recon, memory, portfolio), one @fde skill with field judgment on top, and hooks that make it automatic. Claude Code plugin and any agent that loads skills.",
"bin": {
"fdeops": "bin/install.js",
Expand Down
2 changes: 1 addition & 1 deletion plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "fdeops",
"version": "3.11.0",
"version": "3.11.1",
"description": "Engagement fieldbook for Forward Deployed Engineers: per-client memory in local .fde/ files, one @fde skill, land to close methodology. Local-only, no network.",
"author": {
"name": "Subash Natarajan",
Expand Down
4 changes: 2 additions & 2 deletions skills/fde/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ When NOT to interrogate or challenge: unambiguous one-liners, mechanical ops, FD
- Data tagged `<private>` (sacred data, PHI, cardholder, classified) is **redacted from CLI, dashboard, and hook-injected context**. Do **not** open raw `<private>` blocks with file tools (that bypasses redaction) or paste them into prompts/subagents - work around them, never with them.
- Locked-down engagement (no AI on their code)? Use the CLI + the fieldbook only. The memory layer is the FDE's own notes, not customer code.

**Engagement path - zero ceremony.** Run `fde resume` (fallback: `node ~/.claude/fdeops/fde.js resume`). The **workspace registry** (written once by `fde resume --init <name>`) is the normal path; resolution order is env var override → registry → pointer file → workspace-name match (read-only) → `./.fde`. Writes require a bind (or `FDEOPS_ENGAGEMENT`), not folder name alone. It prints a **bounded** view of `context.md` - the curated head (state, next action) plus the most recent activity, with the older session log collapsed (use `fde resume --full` when you genuinely need the whole history). If it reports NO ENGAGEMENT: confirm the client name in conversation (one question), then run `fde resume --init <name>` yourself - the one setup step; the FDE never runs setup commands. Never install fdeops on infrastructure the FDE does not control.
**Engagement path - zero ceremony.** Run `fde resume` (fallbacks, in order: `node ~/.claude/fdeops/fde.js resume`, then `npx --yes fdeops resume` - the CLI is one command away on any machine with Node, so reach for it before doing memory work by hand). The **workspace registry** (written once by `fde resume --init <name>`) is the normal path; resolution order is env var override → registry → pointer file → workspace-name match (read-only) → `./.fde`. Writes require a bind (or `FDEOPS_ENGAGEMENT`), not folder name alone. It prints a **bounded** view of `context.md` - the curated head (state, next action) plus the most recent activity, with the older session log collapsed (use `fde resume --full` when you genuinely need the whole history). If it reports NO ENGAGEMENT: confirm the client name in conversation (one question), then run `fde resume --init <name>` yourself - the one setup step; the FDE never runs setup commands. Never install fdeops on infrastructure the FDE does not control.

**You run the `fde` CLI for deterministic work - never improvise shell, never hand the command to the FDE:**

Expand All @@ -96,7 +96,7 @@ When NOT to interrogate or challenge: unambiguous one-liners, mechanical ops, FD

**The debrief verb.** Highest-frequency loop. When the FDE shares notes or says "debrief": **you** run the smart path (write notes to a temp file if needed). `--smart` writes a propose file via deterministic heuristics (existing prefixes + light keywords); authentic rambling notes often land mostly in context until **you** rewrite lines with type prefixes. Show the proposed routing in plain language. Only `--apply` (or pipe prefixed lines) after they confirm. Never ask them to run the CLI. Detail: `references/debrief.md`.

CLI missing → use the manual fallbacks inside each reference (still you write files; still never ask the FDE to run setup).
CLI genuinely unavailable (no Node, offline, npx blocked) → use the manual fallbacks inside each reference (still you write files; still never ask the FDE to run setup). A skill-only install is not "unavailable": run the verb through `npx --yes fdeops …` so the gates, dating and redaction still hold.

**Token model - where the cost goes.** Deterministic work is the CLI's job and costs **zero model tokens**: memory writes, recon, receipts, status, dashboard, and the bounded `fde resume`. Session-start hooks inject **TRIAGE + bounded `context.md` + a one-line pointer** - never this full skill body (that loads only when `@fde` triggers). Spend tokens only on judgment - reading the situation, routing, running the phase method, writing the artifact. Three rules keep a full day of FDE work cheap: load the router first and pull **one** reference only when you route to it; never dump a whole `.fde/` file into context - read the bounded resume, or `fde receipts <term>` for a targeted slice; don't re-read files you already have. The expensive model should fire for real decisions, not for plumbing the CLI already does.

Expand Down
Loading