Skip to content

Repository files navigation

Frog

Automated friction logging for agents.


VersionMIT License

Problem · Solution · Quick Prompt · Setup · Usage

Problem

An agent hits friction constantly, and notices all of it. That makes it the best friction logger you have, and the worst at keeping one: each workaround goes unrecorded, and the next agent starts from nothing.

Nobody who could fix the friction hears about it either. Keeping the log by hand does not work: you stop noticing what to write, and nothing removes the entries you did write. The list goes stale, and a stale list goes unread.

Steve Ruiz describing a papercuts CLI for agents

Solution

Frog gives the agent somewhere to put it. Each entry is a directory in .agents/friction-log/ holding the write-up and whatever reproduces it, committed with the code and written the moment friction is hit. The agent reads them before it starts guessing.

Each entry is then reported as an issue, so somebody owns it, and deleted once that issue closes, so the log only ever holds what is still unresolved. Friction in a dependency can be reported to that project instead, if it has opted in.

Quick Prompt

Prompt your agent:

Read https://frog.fm, and set up Frog in my project.

Setup

1. Install Frog (optional)

Install a standalone executable:

curl -fsSL https://frog.fm/install | sh
irm https://frog.fm/install.ps1 | iex

Or install Frog globally:

npm install -g frog
pnpm add -g frog
bun add -g frog

2. Initialize Frog

If you installed Frog:

frog init

If you skipped installation, use your package manager:

npx frog init
pnpx frog init
bunx frog init
yarn dlx frog init

You can use these runners with any Frog command, e.g. npx frog list.

3. Choose Automation Method

Frog supports two automation methods. If an agent is doing the setup, it should prompt the user before changing repository access or adding a workflow:

  • Install the Frog GitHub App and add the App mode workflow for pull-request comments, forks, and cross-repository reporting.
  • Use the Action-only mode workflow for same-repository automation without granting a third-party App access.

Choose one method per repository. Running both can create duplicate issues.

Workflow

See the original lifecycle in wevm/frog-demo, where an agent adding a health endpoint hit a config loader that turns a missing environment variable into the string "undefined", and logged it on the way past. These linked setup commits predate the least-privilege App workflow; use the current setup below.

StepWhat happensExample
1Agent hits friction while working and runs frog log
2The entry commits alongside the change that provoked it0de4ab6
3Frog comments on the pull request, naming what it found#1
4Frog reports the entry as an issue and writes its issue: link#2
5You fix the friction and close the issue#3
6Frog opens a pull request deleting the resolved entry#4
7Merging leaves the log holding only what is still unresolvede4ac13d
Action-only workflow

Action-only uses the repository's workflow and GITHUB_TOKEN, without installing the Frog GitHub App:

StepWhat happensExample
1Run frog init, choose Action-only, and add the repository workflow.5a3142b
2An agent hits friction and runs frog log; the report uses the repository's friction issue form.friction.md
3Frog reports the friction as an issue and opens or updates one accumulating frog/sync pull request.#1 · #2
4A fix closes the issue.#3
5The issue event or next scheduled run updates the same frog/sync pull request to delete the resolved report.#2
6Merging leaves the log holding only unresolved reports.900ea2c

Usage

Add Logs

Records one friction as an entry: a directory holding the write-up and anything needed to reproduce it. Prompts for the details in a terminal, or takes them as flags.

--publish reports it as an issue immediately. Otherwise it stays pending until the next frog publish.

frog log
.agents/friction-log/20260725143012-pnpm-test-files/
friction.md the write-up
artifacts/ optional, whatever reproduces it

View Logs

Shows every unresolved entry: what it is, whether it has been reported, where it is targeted, and whether it ships a reproduction. Exits 1 on an entry that fails to parse, so it doubles as a CI check.

frog list

Logging Upstream

Reports friction to another project instead of your own. A target is an npm package or an owner/repo, and it has to have opted in: targets lists the ones your dependencies declare.

A package names its repository through the standard repository field, and consent is then read from that repository's own default branch. So nothing a package says can send a report somewhere that has not itself agreed to receive one.

Naming a target also scaffolds the entry from that project's GitHub issue form, so the report answers the questions it actually asks rather than Frog's own. A project that names no form keeps Frog's sections.

frog targets
frog log --target viem

Accept Inbound Logs

Accept friction reported by other repositories with .agents/friction-log/config.json:

{
"$schema": "https://unpkg.com/frog/schema.json",
"inbound": {
"enabled": true
}
}

frog init enables inbound reports by default. Run frog init --no-inbound to initialize without accepting inbound reports.

Store Logs in a Database

Store friction logs in a shared database so multiple agents and applications can record and inspect them.

export FROG_DATABASE_URL=postgres://...
frog migrate
frog list

Database Support

DatabaseStatusFactory
PostgreSQLAvailableStore.postgres({ connectionString })
SQLiteComing soon
Cloudflare D1Coming soon

CLI Reference

frog — Automated friction logging for agents.
Usage: frog <command>
Commands:
init Create the friction log, config, and issue form.
list List entries with their state.
log Write a friction entry.
migrate Create or upgrade the selected store.
publish Report pending entries as GitHub issues.
resolve Remove one resolved friction entry.
sync Reconcile entries against issue state.
targets List dependencies that accept friction reports.
Integrations:
completions Generate shell completion script
mcp Register as MCP server (add, doctor)
skills Sync skill files to agents (add, list)
Global Options:
--filter-output <keys> Filter output by key paths (e.g. foo,bar.baz,a[0,3])
--format <toon|json|yaml|md|jsonl> Output format
--full-output Show full output envelope
--help Show help
--llms, --llms-full Print LLM-readable manifest
--mcp Start as MCP stdio server
--schema Show JSON Schema for command
--token-count Print token count of output (instead of output)
--token-limit <n> Limit output to n tokens
--token-offset <n> Skip first n tokens of output
--version Show version

Automation Modes

GitHub App or Action-only?

Choose the GitHub App for pull-request feedback, forks, cross-repository reporting, or durable event processing. Choose Action-only when same-repository automation and avoiding a third-party App grant matter most. Choose one method per repository; running both can create duplicate issues.

AreaGitHub AppAction-only
TrustContents read; issues and pull requests write. The workflow owns source writes.Uses this repository's GITHUB_TOKEN; no third-party App installation.
ScopeCross-repository reporting and reconciliation where installed and allowed.Same repository only; target: entries stay deferred.
Pull requestsReports during the pull request and posts or updates one comment.Reports after merge, without commenting on the author's pull request.
ForksInstallation credentials work independently of the fork token.Cannot safely report from fork pull requests.
ReconciliationApp webhooks signal the repository workflow, with durable retries and a daily sweep.Repository issue events trigger the workflow, with a daily sweep.
DeliveryThe App returns issue state through OIDC; the repository workflow updates frog/sync.The repository workflow reports issues and updates frog/sync.
SetupNeeds the App, the App workflow, and Actions-created pull requests enabled.Needs the Action-only workflow and Actions-created pull requests enabled.
OperationsUses the App service and Actions minutes.Uses Actions minutes; no service to run.

Before using either method, enable Allow GitHub Actions to create and approve pull requests under Settings > Actions > General. Pull-request checks created by GITHUB_TOKEN wait for a user with write access to approve each workflow run. Push-only workflows do not run; pass a personal access token or App token as token when they are required.

Both methods update one accumulating frog/sync pull request:

  • A protected default branch needs a human to merge frog/sync. Complete runs force-update the branch; deferrals preserve the existing pull request. Do not hand-edit it.
  • @v1 moves with compatible releases. Pin both a full action commit SHA and an exact version input to fix Frog itself; npm still resolves the published package's dependency ranges at install time.
  • Never run it on pull_request. Fork tokens are read-only, and pull-request config is untrusted. pull_request_target is unsafe for the same reason.
  • One malformed friction.md fails the run because the log cannot be read partially.

App Mode

Install the Frog GitHub App, then create .github/workflows/friction-log.yml:

name: Friction Logon:
push:
issue_comment:
types: [created, edited]workflow_dispatch:
schedule:
- cron: '0 0 * * *'concurrency:
group: friction-logcancel-in-progress: falsepermissions: {}jobs:
friction-log:
name: Friction Log# The Action validates the exact Frog-owned control issue and comment.if: >- (github.event_name != 'push' || github.ref_name == github.event.repository.default_branch) && (github.event_name != 'issue_comment' || github.actor_id == '309546769')runs-on: ubuntu-latestpermissions:
contents: writeid-token: writeissues: nonepull-requests: writesteps:
- name: Clone repositoryuses: actions/checkout@v6with:
persist-credentials: falseref: ${{ github.sha }}
- name: Report and reconcile frictionsuses: wevm/frog/reconcile@v1

The App has read access to repository contents and write access to issues and pull requests, but it cannot write source. Its pull-request comment token is scoped to one repository and has no Contents access. The workflow authenticates to the App with GitHub OIDC. The App returns issue state only; the Action derives every change from the checked-out reports and writes it with this repository's GITHUB_TOKEN. GitHub's Contents permission covers the whole selected repository, not only the friction log. Choose Action-only if you do not want to grant that read access.

Action-only Mode

frog init describes both methods without choosing one. For Action-only, create .github/workflows/friction-log.yml without installing the App:

name: Friction Logon:
push:
issues:
types: [closed, reopened]workflow_dispatch:
schedule:
- cron: '0 0 * * *'concurrency:
group: friction-logcancel-in-progress: falsepermissions: {}jobs:
friction-log:
name: Friction Logif: >- (github.event_name != 'push' || github.ref_name == github.event.repository.default_branch) && (github.event_name != 'issues' || github.event.issue.user.login == 'github-actions[bot]')runs-on: ubuntu-latestpermissions:
contents: writeissues: writepull-requests: writesteps:
- name: Clone repositoryuses: actions/checkout@v6with:
persist-credentials: falseref: ${{ github.sha }}
- name: Report and reconcile frictionsuses: wevm/frog/action@v1with:
issue-author: github-actions[bot]

The workflow uses the repository's own GITHUB_TOKEN to report pending entries, reconcile issue state, and update frog/sync. Frog is installed under RUNNER_TEMP, isolated from the repository's dependencies. The explicit issue-author prevents another user's issue from being treated as a Frog report. If you pass a personal access token or App token, set this input and the workflow's issues guard to that token's exact user or bot login.

License

MIT

About

Automated friction logging for agents.

Topics

Resources

Code of conduct

Stars

245 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages