Install Foreloop
Two things install: the CLI, for driving Foreloop from a terminal or anything that can run one, and the feedback widget, for collecting feedback from inside your own product. They are independent — install either, or both.
The CLI
Projects, loops, intentions, stories and tasks from a terminal — and from anything that can run one, including coding agents and cron.
npm i -g foreloopnpx foreloop … works without installing, but a global install is the recommendation: this is a tool you reach for many times a day, and npx re-resolves the package on every invocation.
Authenticate
Create a key in Settings → API keys (sign-in required). The CLI purpose reaches as far as you do in the web app — it claims and runs work, approves contracts and ships releases — so it belongs in your shell and nowhere else: never in browser code, never in a repository.
foreloop auth login # the prompt hides the input
foreloop init # install the task-executor skill in this repo
foreloop tasks ready # open tasks whose contract is approvedRun foreloop --help for the common path and the output conventions, and foreloop <group> --help to list a group's commands — everyday ones first, one-off maintenance after.
Built for scripts and agents
--jsonworks on any command and has a stable shape. Additive changes only.- Exit codes are meaningful:
0ok,1failed,2auth,3usage,4confirmation required. A query that finds nothing still exits0, so callers branch on the payload rather than on failure:foreloop tasks ready --json | jq -e '.tasks | length > 0' && run-my-agent - Unknown commands and flags fail outright rather than guessing at intent.
FORELOOP_TOKENoutranks any stored credential, so CI needs no login step.FORELOOP_BASE_URLpoints the CLI at a non-production API.
The package re-exports @foreloop/feedback in full, so one dependency covers both the CLI and the widget below. Embedding the widget and nothing else? @foreloop/feedback alone is smaller and also ships the built browser asset.
The feedback widget
The widget lets people send feedback, bugs, and ideas from inside your product — annotated, screenshotted, and routed into your Foreloop organization as signals. One install covers every route, and each submission carries its own page URL.
1. Get a write-only key
Keys are generated in Foreloop: Widget → Installation (sign-in required). A widget key carries only the signal:write scope — it can submit feedback and nothing else, which is why it may live in browser code and in your repository. Never embed a key with broader scopes.
The key is also what decides where submissions land: they arrive in the organization the key belongs to — yours — whoever sent them. Mint your own rather than reusing one from elsewhere, and the widget needs no endpoint configured, because it posts to https://foreloop.com on its own.
Every snippet below shows flpk_YOUR_WRITE_ONLY_KEY where your key belongs. The in-app page hands you the same snippets with the key already in them.
2. Pick an install path
The same widget with the same options either way — the two differ only in how its code reaches the page.
Hosted
One tag, and we serve the widget. Right for most web projects — Webflow, Framer, WordPress, or any hand-written HTML. Nothing to build, and published fixes reach your site without you redeploying.
Installed
A package in your bundle, for teams building a full app. Costs you a build step and buys flexibility: pass the signed-in user, re-initialize when they change, and serve the asset yourself.
Hosted — one tag
- Paste this into the one layout template every page shares, immediately before the closing
</body>tag — the same place you would put Google Analytics or any other analytics script.
On Webflow, Framer, Squarespace and the like, that is the site-wide custom code field for the end of<script src="https://cdn.jsdelivr.net/npm/@foreloop/feedback@latest/dist/foreloop-feedback.js" data-api-key="flpk_YOUR_WRITE_ONLY_KEY" async ></script><body>— not the per-page one. Keepasync: the widget waits for the DOM itself. - Reload your site. A launcher appears in the lower-right corner. Paste the tag in one place only.
Installed — the npm package
- Run this in your project root.
cd path/to/your-app npm install @foreloop/feedback - Paste this into your root layout — the one file that wraps every page (
app/layout.tsxin Next.js,App.tsxin Vite).
It has to run in the browser only: the initializer touchesimport { initForeloopFeedback } from "@foreloop/feedback"; await initForeloopFeedback({ apiKey: "flpk_YOUR_WRITE_ONLY_KEY", reporterName: signedInUser?.email, });documentand throws during server-side rendering, so in Next.js it needs a"use client"boundary. Call it after the signed-in user is known, and swapsignedInUser?.emailfor your own accessor — omit it for anonymous visitors and the widget asks instead. - Reload your app. A launcher appears in the lower-right corner. The package fetches the widget asset at runtime rather than bundling it, so this path still makes one CDN request.
Options
Each option is a snippet attribute on the hosted path and an initializer property on the installed one.
data-api-key/apiKey— the write-only key. Required.data-project/project— the project submissions target. Omit for the organization default.data-trigger/trigger— a CSS selector for elements of yours. Clicks on any match open the widget, and the floating launcher gives way to a centered modal. Omit it for the launcher.data-reporter-name/reporterName— pre-fills the Email field. Omit for anonymous visitors; the widget never infers identity.data-button-label/buttonLabelanddata-button-color/buttonColor— the launcher's wording and fill. Use the dark and light variants when one colour cannot serve both pages.captureScreenshot— offers optional screen capture. The browser always asks the user what to share.includeUrlEvidence/includeQuery— attach the page URL. Query strings and fragments stay excluded unless you opt in, because they carry tokens and search terms more often than useful context.data-private/data-sensitive— put these on your own elements to mark what can never be selected as an annotation. Inputs are always excluded.
Content-Security-Policy
If your site enforces a CSP, the widget needs four directives:
script-src https://cdn.jsdelivr.net— loads the widget asset, on both paths, because the initializer injects a script tag too. Use'self'when you serve the asset yourself.connect-src https://foreloop.com— submissions are afetchto the Foreloop API.style-src— a nonce, or'unsafe-inline'. The widget injects one<style>element; prefer passing a nonce throughdata-style-nonce.img-src data:— the screenshot preview renders as a data URL.