Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
3566bce
feat(fp-cli): open-source the Cloud CLI as `fp-cli`, command `fp`
NiveditJain Aug 17, 2026
e4f8890
docs(changelog): record the fp-cli open-sourcing (#702)
NiveditJain Aug 17, 2026
c4d9a71
feat(fp-cli): re-establish the agent-skill mirror, now as skills/fp-cli
NiveditJain Aug 17, 2026
ae14887
fix(fp-cli): remove a customer identifier, restore publish authorization
NiveditJain Aug 17, 2026
29d04e8
fix(fp-cli): stop a stdin read draining a query, and a tripwire namin…
NiveditJain Aug 17, 2026
7900b01
chore: re-trigger CI after GitHub 429s in Set up job
NiveditJain Aug 17, 2026
dc6364e
chore: re-trigger CI again — GitHub Actions still in a partial outage
NiveditJain Aug 17, 2026
80affea
chore: re-trigger CI (attempt 4) — one job per run still losing setup…
NiveditJain Aug 17, 2026
7670c90
feat(sdk): open-source the telemetry SDK as `failproofai-sdk` in sdk/…
NiveditJain Aug 17, 2026
cd52279
fix(sdk): make the zero-dependency check work on Python 3.10
NiveditJain Aug 17, 2026
7691199
test(sdk): stop the configure() thread-safety test depending on execu…
NiveditJain Aug 17, 2026
3b302ca
fix(sdk): address four CodeRabbit findings — all four were real
NiveditJain Aug 17, 2026
bc039ac
fix(fp-cli): two docs claims that contradict the shipped code
NiveditJain Aug 17, 2026
b30c492
fix(fp-cli): two --help examples that fail when you run them
SiddarthAA Aug 18, 2026
10364f3
fix(sdk): seven ways the SDK lost events without saying so
SiddarthAA Aug 18, 2026
18ef5c3
feat(fp-cli): move the session into ~/.failproofai/fpcli/cli-auth.json
SiddarthAA Aug 18, 2026
acfca52
fix(fp-cli): name the right stale session file for FP_HOME users
SiddarthAA Aug 18, 2026
e3c7e71
fix(fp-cli): three help strings still printed the pre-move config path
SiddarthAA Aug 18, 2026
ce2012d
feat(fp-cli): adopt a pre-move session instead of signing the machine…
SiddarthAA Aug 18, 2026
3b3d666
test(fp-cli): adoption must not resurrect a session after logout
SiddarthAA Aug 18, 2026
5bacab7
fix(sdk): stop the test suite writing into the developer's real spool
SiddarthAA Aug 18, 2026
33cc78a
feat(sdk)!: default the spool to ~/.failproofai/custom-agents
SiddarthAA Aug 18, 2026
d1b16b1
Merge origin/main into feat/fp-cli
SiddarthAA Aug 18, 2026
2fa3e57
test(sdk): pin what the SDK may create inside ~/.failproofai
SiddarthAA Aug 18, 2026
cc28451
fix(sdk): four review findings — durability, u32 range, NaN, cancella…
SiddarthAA Aug 18, 2026
c99dc2d
fix(sdk): five bugs found by adversarial testing, two of them crashes
SiddarthAA Aug 18, 2026
2fe57f4
test(sdk): stop the spool-contract test aborting the suite outside th…
SiddarthAA Aug 18, 2026
bb1cc99
test(fp-cli): guard the credential path against drifting from the reg…
SiddarthAA Aug 19, 2026
3c8bc31
[fp-cli] fp policies, fp fleet and fp guardrails — the dashboard's en…
SiddarthAA Aug 19, 2026
7215375
Merge origin/main into feat/fp-cli
SiddarthAA Aug 20, 2026
ee735f5
[sdk] Native support for LangChain/LangGraph, CrewAI, LlamaIndex and …
SiddarthAA Aug 20, 2026
84a7b3c
ci: ignore an unfixable chromadb advisory that cannot reach a user
SiddarthAA Aug 20, 2026
ae10911
docs(changelog): one Docs section per version, not two
SiddarthAA Aug 20, 2026
6d416b4
ci: ignore the advisory under its primary id, not only its alias
SiddarthAA Aug 20, 2026
3a0e57b
ci: make the root osv-scanner.toml govern every lockfile it scans
SiddarthAA Aug 20, 2026
0c0ff4c
fix(fp-cli): stop the customer tripwire from publishing the name it h…
SiddarthAA Aug 20, 2026
e3271fc
docs(sdk): correct the spool root the README tells readers to look in
SiddarthAA Aug 20, 2026
9bbccaa
fix(failproofaid): --help printed nothing and started the daemon
SiddarthAA Aug 20, 2026
320598a
ci(sdk): actually run the framework integration suites
SiddarthAA Aug 20, 2026
ad48c92
chore(fp-cli): stop fixtures and help text naming a real domain
SiddarthAA Aug 20, 2026
f1e68f7
fix(fp-cli): `fp issues show <malformed-id>` never reached its not-fo…
SiddarthAA Aug 20, 2026
de388b1
fix(collect): park a batch the server stored none of, instead of dele…
SiddarthAA Aug 20, 2026
6372ecf
fix(fp-cli): resolve a member by the email the caller actually typed
SiddarthAA Aug 20, 2026
b672543
fix(sdk): document model_response's real keyword, and guard the class
SiddarthAA Aug 20, 2026
bed3d39
docs(integrations): let the page shape match what is being explained
SiddarthAA Aug 20, 2026
ab4d76c
docs(skill): correct three stale claims, and guard the prose
SiddarthAA Aug 20, 2026
d7dd7cc
fix(sdk): stop $AGENTEYE_HOME from moving the spool off the umbrella
SiddarthAA Aug 20, 2026
a720f38
fix(fp-cli): sum every policy source in the decision timeline, not se…
SiddarthAA Aug 20, 2026
9634840
docs(cloud-cli): stop denying commands the CLI has, and name the real…
SiddarthAA Aug 20, 2026
362de76
docs(fp-cli): compose needs policies:write, not agent:use
SiddarthAA Aug 20, 2026
95e4b24
feat(sdk): raise LangChain's capture limit, and tie the event budget …
SiddarthAA Aug 21, 2026
05b47fa
Merge origin/main into feat/fp-cli
NiveditJain Aug 21, 2026
45a1faf
fix(sdk): stop the shipped SIGTERM recipe from deadlocking the host p…
SiddarthAA Aug 24, 2026
4737073
fix(sdk): make the adapters' size budget, privacy switch and error ac…
SiddarthAA Aug 24, 2026
e6025f7
fix(sdk): stop the sdist poisoning a real spool, and make four guards…
SiddarthAA Aug 24, 2026
7c4c10f
fix(fp-cli): stop the CLI reporting success it did not have, and leak…
SiddarthAA Aug 24, 2026
f16eae8
fix(collect): stop the delivery-health signal reporting success while…
SiddarthAA Aug 24, 2026
790a7b0
docs: correct nine claims the code disproves, and guard the two that …
SiddarthAA Aug 24, 2026
e354054
ci: make the publish gate test the adapters, and the workflow guards …
SiddarthAA Aug 24, 2026
aa87d6a
docs(changelog): record the review fixes under 1.0.2-beta.0
SiddarthAA Aug 24, 2026
236534f
fix(fp-cli): relock for the corrected typer floor
SiddarthAA Aug 24, 2026
01f6799
Merge remote-tracking branch 'origin/main' into feat/fp-cli
SiddarthAA Aug 24, 2026
bd9b68e
Merge remote-tracking branch 'origin/feat/fp-cli' into feat/fp-cli
SiddarthAA Aug 24, 2026
4ce3b58
fix(sdk): bound the queue by measured bytes, and stop an oversized ev…
SiddarthAA Aug 24, 2026
e4b51bf
fix(collect): stop a partially-accepted batch destroying the events i…
SiddarthAA Aug 24, 2026
21cec5b
fix(fp-cli): stop a failed membership lookup reading as "you belong t…
SiddarthAA Aug 24, 2026
915a592
ci: keep the publishing identity and the mirror's code out of the sam…
SiddarthAA Aug 24, 2026
35c4d52
docs(changelog): record the second-review fixes
SiddarthAA Aug 24, 2026
8306b91
fix(fp-cli): stop a busy machine being reported as a broken policy
SiddarthAA Aug 24, 2026
2f18ac4
chore(release): open both Python packages at 0.0.1b1
NiveditJain Aug 24, 2026
51738dd
feat(ci): version management pipelines for fp-cli and failproofai-sdk
NiveditJain Aug 24, 2026
01977ab
docs(claude): record the Python packages' release scheme
NiveditJain Aug 24, 2026
cc9a710
fix(ci): close the re-run bypass in the PyPI publish guard
NiveditJain Aug 24, 2026
8762e27
fix(sdk): stop the writer thread flushing into whichever test is running
NiveditJain Aug 24, 2026
9c81113
docs(ci): point PyPI setup at the page that exists for an unregistere…
NiveditJain Aug 24, 2026
2ecb250
feat(ci): GitHub Releases and changelogs for both Python packages
NiveditJain Aug 24, 2026
e385535
refactor: rename the Cloud CLI distribution to fp-cloud-cli
NiveditJain Aug 24, 2026
60f4dc8
docs: restructure the agent-instrumentation docs, and make the star c…
SiddarthAA Aug 24, 2026
dd8cf5a
Merge remote-tracking branch 'origin/feat/fp-cli' into feat/fp-cli
SiddarthAA Aug 24, 2026
146cacf
fix(docs): move the 14 locale SDK reference copies with their English…
NiveditJain Aug 24, 2026
dac8639
test: cover the live star count and the Python package registration
NiveditJain Aug 24, 2026
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
16 changes: 16 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,19 @@ updates:
rust-dependencies:
patterns:
- "*"

# The `fp` CLI (PyPI: fp-cli) — the only Python in the repo. Its lockfile is
# `fp-cli/uv.lock`, so the ecosystem is `uv`, and the directory is the package
# root rather than `/`. Grouped for the same reason as the Rust tree: the whole
# dependency set is verified together by one pytest run, and separate PRs each
# rebuild the lockfile the others just changed.
- package-ecosystem: uv
directory: /fp-cli
schedule:
interval: weekly
day: monday
open-pull-requests-limit: 5
groups:
python-dependencies:
patterns:
- "*"
58 changes: 58 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,64 @@ jobs:
target
key: cargo-${{ runner.os }}-${{ hashFiles('rust-toolchain.toml', 'Cargo.lock', 'crates/*/Cargo.toml') }}

# The `fp` CLI (PyPI: fp-cli). The only Python in this repo, and the only job that
# tests it — none of the bun/cargo jobs above look at fp-cli/ at all. It is matrixed
# across the Python versions pyproject.toml's requires-python advertises, because
# claiming >=3.10 and testing only one of them is how a 3.10 user finds the break.
fp-cli:
runs-on: ubuntu-latest
defaults:
run:
working-directory: fp-cli
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.13"]
steps:
- uses: actions/checkout@v7.0.1

- uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-dependency-glob: fp-cli/uv.lock

- name: Install dependencies
run: uv sync --extra dev --python ${{ matrix.python-version }}

- name: Test
run: uv run pytest tests/ -q

- name: Build the distribution
run: uv build

# A stale `include = [...]` in [tool.setuptools.packages.find] builds a
# SUCCESSFUL but EMPTY wheel — pip installs it and the console script then
# ImportErrors. Nothing else in this job would notice, so assert the payload.
- name: Verify the wheel actually contains the package
run: |
python3 - <<'PY'
import glob, sys, zipfile
wheel = glob.glob("dist/*.whl")[0]
names = zipfile.ZipFile(wheel).namelist()
modules = [n for n in names if n.startswith("fp_cli/") and n.endswith(".py")]
print(f"{wheel}: {len(modules)} modules")
if len(modules) < 20:
sys.exit(f"wheel looks empty — only {len(modules)} modules under fp_cli/")
PY

# `fp` is the contract users type. Prove the entry point resolves from a clean
# install of the built artifact, not from the source tree.
- name: Smoke-test the installed console script
run: |
uv venv /tmp/fp-smoke
VIRTUAL_ENV=/tmp/fp-smoke uv pip install dist/*.whl
/tmp/fp-smoke/bin/fp --version
/tmp/fp-smoke/bin/fp help > /tmp/fp-help.txt
if grep -qi agenteye /tmp/fp-help.txt; then
echo '::error::retired product name present in the fp help output'
exit 1
fi

test:
runs-on: ubuntu-latest
strategy:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/osv-scanner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ jobs:
scan-args: |-
--lockfile=bun.lock
--lockfile=Cargo.lock
--lockfile=fp-cli/uv.lock
# Only the schedule run notifies — nothing on main touched the lockfile,
# so nobody is watching it the way a PR author watches their own checks
# or a push failure shows up against the commit they just merged. Same
Expand Down
84 changes: 84 additions & 0 deletions .github/workflows/publish-fp-cli.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: Publish fp-cli to PyPI

# The `fp` CLI (PyPI project: fp-cli) ships on its own cadence, separate from the npm
# package and the daemon binaries in publish.yml. It is a pure-Python wheel with no
# platform matrix and no release assets, so it has nothing to share with that pipeline
# beyond the registry credentials it does not use.
#
# AUTHENTICATION IS PyPI TRUSTED PUBLISHING (OIDC) — there is no PYPI_API_TOKEN secret.
# This requires a one-time, out-of-band setup on PyPI that CANNOT be done from a PR:
#
# PyPI project `fp-cli` -> Manage -> Publishing -> Add a new pending publisher
# Owner: FailproofAI
# Repository: failproofai
# Workflow name: publish-fp-cli.yml
# Environment: (leave blank)
#
# Until that publisher exists the `publish` job fails at the upload step with an OIDC
# error. Configure it BEFORE the first release, not after.

on:
workflow_dispatch:
inputs:
dry_run:
description: Build and verify, but do not upload to PyPI
type: boolean
default: false

concurrency:
group: publish-fp-cli
cancel-in-progress: false

jobs:
publish:
runs-on: ubuntu-latest
defaults:
run:
working-directory: fp-cli
permissions:
# Required for Trusted Publishing. `contents` stays at the default read.
id-token: write
Comment thread
NiveditJain marked this conversation as resolved.
Outdated
steps:
- uses: actions/checkout@v7.0.1

- uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-dependency-glob: fp-cli/uv.lock

- name: Install dependencies
run: uv sync --extra dev

# Never publish a version whose tests do not pass. This duplicates the ci job on
# purpose: a workflow_dispatch can target any ref, including one CI never ran.
- name: Test
run: uv run pytest tests/ -q

- name: Build
run: uv build

- name: Verify the artifacts before uploading
run: |
python3 - <<'PY'
import glob, sys, zipfile
wheel = glob.glob("dist/*.whl")[0]
names = zipfile.ZipFile(wheel).namelist()
modules = [n for n in names if n.startswith("fp_cli/") and n.endswith(".py")]
if len(modules) < 20:
sys.exit(f"refusing to publish an empty wheel ({len(modules)} modules)")
if not any(n.endswith("LICENSE") for n in names):
sys.exit("refusing to publish without a LICENSE in the wheel")
print(f"{wheel}: {len(modules)} modules, licence present")
PY

- name: Report the version being published
run: |
VERSION=$(uv run python -c 'from fp_cli._version import __version__; print(__version__)')
echo "fp-cli version: ${VERSION}"
echo "### Publishing \`fp-cli\` ${VERSION}" >> "${GITHUB_STEP_SUMMARY}"

- name: Publish to PyPI
if: ${{ !inputs.dry_run }}
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: fp-cli/dist/
127 changes: 127 additions & 0 deletions .github/workflows/sync-fp-cli-skill.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
name: Sync fp-cli skill

# One-directional mirror — MUST be run from `main`:
# FailproofAI/failproofai fp-cli/skill/ ──▶ FailproofAI/skills skills/fp-cli/
#
# This replaces `sync-skill.yml` in the private FailproofAI/agenteye repo, which
# mirrored the same skill from `cli/skill/` to `skills/agenteye-cli/` before the CLI
# moved here. That workflow was deleted with the CLI.
#
# The skills repo is pull-only — never hand-edit skills/fp-cli/ there; edit
# fp-cli/skill/ here and let this run. It force-pushes ONE stable branch and reuses
# ONE PR (no pileup, no merge conflicts: every run rebuilds off latest main).
#
# One-time setup on FailproofAI/skills (admin):
# • create the label this workflow applies:
# gh label create skill-sync-fp-cli --repo FailproofAI/skills \
# --color 8A63D2 --description "Automated fp-cli skill mirror PRs from FailproofAI/failproofai"
# • delete the now-orphaned skills/agenteye-cli/ folder, which teaches the retired
# `agenteye` command and is no longer synced by anything
# One-time setup on THIS repo (admin):
# • add Actions secret SKILLS_SYNC_PAT — a fine-grained PAT scoped to
# FailproofAI/skills, Contents: Read and write + Pull requests: Read and write.
# The agenteye repo has a secret of the same name; this repo needs its own.
# Until it exists this workflow fails at the clone step.

on:
push:
branches:
- main
paths:
- 'fp-cli/skill/**'
workflow_dispatch:

concurrency:
group: sync-fp-cli-skill
cancel-in-progress: false

permissions:
contents: read # GITHUB_TOKEN only reads this repo; all writes use the PAT

env:
SRC: fp-cli/skill # source of truth (this repo)
DEST_REPO: FailproofAI/skills # mirror target
DEST_SUBDIR: skills/fp-cli # folder overwritten in the mirror
BRANCH: sync/fp-cli # stable bot branch (force-pushed each run)
LABEL: skill-sync-fp-cli
REVIEWERS: NiveditJain,SiddarthAA
WORKDIR: /tmp/skills

jobs:
sync:
name: Mirror skill and open PR
runs-on: ubuntu-latest
steps:
- name: Enforce run-from-main
run: |
if [ "$GITHUB_REF" != "refs/heads/main" ]; then
echo "::error::This workflow must be run from main (got $GITHUB_REF)."
exit 1
fi

- name: Checkout (source of truth)
uses: actions/checkout@v7.0.1

- name: Clone FailproofAI/skills
run: |
git clone --depth=1 \
"https://x:${{ secrets.SKILLS_SYNC_PAT }}@github.com/${DEST_REPO}.git" "$WORKDIR"

- name: Mirror fp-cli/skill/ → skills/fp-cli/
run: |
mkdir -p "$WORKDIR/$DEST_SUBDIR"
rsync -a --delete --exclude '.git' "$SRC"/ "$WORKDIR/$DEST_SUBDIR"/

- name: Validate (skills repo's own gate)
run: python3 "$WORKDIR/scripts/validate-skills.py"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

- name: Commit, push branch, open/refresh PR
env:
GH_TOKEN: ${{ secrets.SKILLS_SYNC_PAT }}
run: |
cd "$WORKDIR"
git config user.name "fp-cli-skill-sync"
git config user.email "github-actions[bot]@users.noreply.github.com"

# `git status --porcelain`, NOT `git diff`: on the first sync of a new skill the
# destination folder does not exist yet, so every mirrored file is UNTRACKED —
# and `git diff` only ever looks at tracked files. It would report clean here and
# skip the publish, passing the run green having shipped nothing. This matters
# immediately: skills/fp-cli/ does not exist yet.
if [ -z "$(git status --porcelain -- "$DEST_SUBDIR")" ]; then
echo "Already in sync — nothing to publish."
exit 0
fi

SHORT_SHA="${GITHUB_SHA::7}"
git switch -c "$BRANCH"
git add "$DEST_SUBDIR"
git commit -m "Sync fp-cli skill from failproofai@${SHORT_SHA}" \
-m "Automated mirror of fp-cli/skill/. Source of truth: FailproofAI/failproofai — do not hand-edit."
git push --force origin "$BRANCH"

BODY="Automated mirror — **do not hand-edit this folder**.

| | |
|---|---|
| Source of truth | [\`FailproofAI/failproofai\`](https://github.com/${GITHUB_REPOSITORY}) → \`${SRC}/\` |
| Target | \`${DEST_SUBDIR}/\` |
| Triggered from | \`main\` @ [\`${SHORT_SHA}\`](https://github.com/${GITHUB_REPOSITORY}/commit/${GITHUB_SHA}) |

This replaces \`skills/agenteye-cli/\`, which mirrored the same skill from the private agenteye repo before the CLI moved here and was renamed to \`fp\`. **That folder is now orphaned and should be deleted** — nothing syncs it, and it teaches the retired \`agenteye\` command.

The skills repo's \`validate-skills.py\` passed. To change the skill, edit \`${SRC}/\` and re-run the **Sync fp-cli skill** workflow — this same PR refreshes."

if gh pr view "$BRANCH" --repo "$DEST_REPO" --json state --jq .state 2>/dev/null | grep -q OPEN; then
echo "PR already open for $BRANCH — branch force-pushed, PR refreshed."
else
gh pr create --repo "$DEST_REPO" --base main --head "$BRANCH" \
--title "Sync fp-cli skill (failproofai@${SHORT_SHA})" \
--body "$BODY" \
--label "$LABEL"
fi

# Reviewers are tolerant: the PR author (PAT owner) can't review their own
# PR, so a failure here must not fail the sync.
gh pr edit "$BRANCH" --repo "$DEST_REPO" --add-reviewer "$REVIEWERS" \
|| echo "::warning::could not request reviewers $REVIEWERS (self-review or missing access?)"
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,13 @@ COMMIT_MSG.tmp
**/.failproofai/bin/
**/.failproofai/run/
**/.failproofai/state/

# Python build and test artefacts from fp-cli/. `/dist` above is the Next.js one at
# the repo root; fp-cli builds into its own nested dist/, which that rule does not
# match, so it needs naming separately.
fp-cli/dist/
fp-cli/.venv/
fp-cli/.pytest_cache/
**/__pycache__/
*.py[cod]
*.egg-info/
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 1.0.1-beta.2 — 2026-08-17

### Features

- Open-source the Cloud CLI as `fp-cli` (command `fp`), moved out of the private AgentEye monorepo into `fp-cli/`. The distribution and the command differ because `fp` was taken on PyPI, and neither is the `failproofai` CLI this repo already builds — that one enforces inside the agent loop, this one reads back what the loop did. It is a hard cut, matching the collector binary's rename: no `agenteye` alias, no retired env-var fallback, no config migration, so scripts calling `agenteye ...` break on upgrade and users run `fp login` once. Env vars move to `FP_*` and the config to `~/.fp/cli.json`. The `X-AgentEye-Org` / `X-AgentEye-Client` headers and the `ae_session` cookie are deliberately unchanged — they are a contract with the dashboard and the Rust server, and renaming them from one side would misroute tenants with a 200 rather than an error. Brings the first Python into the repo: a matrixed `fp-cli` CI job, a Trusted-Publishing PyPI workflow, a `uv` dependabot ecosystem and the lockfile in the osv-scanner gate. Also fixes a README that documented a command renamed long ago and a default it claimed did not exist, a test fixture that ran the suite with TLS verification disabled, and a repo-root probe that would have resolved to the wrong repo here. (#702)

## 1.0.1-beta.1 — 2026-08-16

### Fixes
Expand Down
17 changes: 16 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1208,7 +1208,22 @@ crates/failproofaid/ The daemon binary — socket server + service lif
@failproofai/failproofaid-<os>-<arch> npm packages and as
GitHub Release assets — see "How the daemon binary reaches
users")
__tests__/ Unit + e2e tests (vitest)
fp-cli/ The `fp` CLI for FailproofAI Cloud (Python, uv, pytest).
PyPI dist `fp-cli`; the installed command is `fp` —
they differ because `fp` was taken on PyPI. Talks only
to the Cloud dashboard's /api surface, never to the
Rust server directly. NOT the same thing as the
`failproofai` CLI this repo builds from bin/ + src/:
that one enforces inside the agent loop, this one
reads back what the loop did.
fp_cli/client.py Pure query layer (no printing, no Typer) — the surface
an MCP server would wrap
fp_cli/output.py All rendering, incl. `_TOP_LEVEL_GROUPS`, the
HAND-MAINTAINED top-level help table. A command missing
from it is invisible in `fp help` forever; guarded by
tests/test_help_table_coverage.py
__tests__/ Unit + e2e tests (vitest) — TypeScript only; fp-cli's
tests live in fp-cli/tests/ and run under pytest
examples/ Sample custom policy files
```

Expand Down
7 changes: 7 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,16 @@ failproofai/
├── scripts/ # Dev/start/build helper scripts
├── __tests__/ # Test files
├── examples/ # Example custom hook policies
├── fp-cli/ # The `fp` CLI for FailproofAI Cloud (Python; PyPI: fp-cli)
└── public/ # Static assets
```

> `fp-cli/` is the one Python component in an otherwise TypeScript + Rust repo. It
> is self-contained: its own `pyproject.toml`, its own `uv.lock`, its own pytest
> suite, and its own CI job (`fp-cli` in `ci.yml`). It is not part of the npm
> package, the Next.js build, or the Cargo workspace, and it versions independently
> of the root `package.json` — see CLAUDE.md.

### Key Subsystems

| Directory | Description |
Expand Down
Loading