Reviews pull requests that use the fp-go library against its conventions: v2 imports, data-last arguments, point-free style, Result over Either and idiomatic monads.
Install the "fp-go-pr-review" agent skill from https://github.com/IBM/fp-go/tree/main/skills/fp-go-pr-review into .claude/skills/fp-go-pr-review/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "fp-go-pr-review", then confirm the skill loads.
Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Type this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
skills CLI
$ npx skills add IBM/fp-go --skill fp-go-pr-review -a codex
Project install goes to .agents/skills/; add -g for ~/.codex/skills/.
Install the "fp-go-pr-review" agent skill from https://github.com/IBM/fp-go/tree/main/skills/fp-go-pr-review into .agents/skills/fp-go-pr-review/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "fp-go-pr-review", then confirm the skill loads.
Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
skills CLI
$ npx skills add IBM/fp-go --skill fp-go-pr-review -a cursor
Project install goes to .agents/skills/; add -g for ~/.cursor/skills/.
Install the "fp-go-pr-review" agent skill from https://github.com/IBM/fp-go/tree/main/skills/fp-go-pr-review into .cursor/skills/fp-go-pr-review/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "fp-go-pr-review", then confirm the skill loads.
Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
skills CLI
$ npx skills add IBM/fp-go --skill fp-go-pr-review -a gemini-cli
Project install goes to .agents/skills/; add -g for ~/.gemini/skills/.
Install the "fp-go-pr-review" agent skill from https://github.com/IBM/fp-go/tree/main/skills/fp-go-pr-review into .gemini/skills/fp-go-pr-review/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "fp-go-pr-review", then confirm the skill loads.
Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
GitHub CLI
$ gh skill install IBM/fp-go fp-go-pr-review
Installs for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
skills CLI
$ npx skills add IBM/fp-go --skill fp-go-pr-review -a github-copilot
Project install goes to .agents/skills/; add -g for ~/.copilot/skills/.
Install the "fp-go-pr-review" agent skill from https://github.com/IBM/fp-go/tree/main/skills/fp-go-pr-review into .github/skills/fp-go-pr-review/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "fp-go-pr-review", then confirm the skill loads.
GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
skills CLI
$ npx skills add IBM/fp-go --skill fp-go-pr-review -a opencode
OpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
Install the "fp-go-pr-review" agent skill from https://github.com/IBM/fp-go/tree/main/skills/fp-go-pr-review into .opencode/skills/fp-go-pr-review/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "fp-go-pr-review", then confirm the skill loads.
OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Facts
Skill name
fp-go-pr-review
GitHub stars
2k
Token cost
~6.4k tokens
SKILL.md length
1,564 words
Files
1
Skills in repo
10
Repo updated
First seen
Licence
Apache-2.0
At a glance
Reviews pull requests that use the fp-go library against its conventions: v2 imports, data-last arguments, point-free style, Result over Either and idiomatic monads.
Works in 12 steps: Import Path Validation → Data-Last Principle → Point-Free Style → …
Reviewing a pull request that adds fp-go code
SKILL.md covers Overview, When to Use This Skill, Review Checklist and Review Process, plus 3 more sections
Calls git, go and gh
What it does
The checklist covers code that uses `github.com/IBM/fp-go/v2` and needs Go 1.24 or newer for generic type aliases. Imports must use v2 and never v1, flagged critical because the versions are incompatible, and import aliases must follow the canonical table so one letter never stands for two packages. Operations must be data-last, with the data being transformed as the final argument, and data-first calls are a high-severity finding because they break composition.
Style checks prefer composing named functions with Flow and Pipe over inline lambdas, which are acceptable only at the leaves such as field accessors, lens setters, multi-field formatters and side-effecting sinks. This is rated medium severity. The checklist also prefers Result over Either when the error type is Go's error, and the description adds lens patterns and proper monad usage. Each rule comes with a severity and sample code, and the excerpt is cut off after the Result rule.
When your agent uses it
Reviewing a pull request that adds fp-go code
Checking changes for data-first calls or v1 imports
Reviewing functional composition and monad usage in Go
Example prompts
“Review this PR branch for fp-go convention violations.”
“Check whether our new pipeline uses Flow and Pipe instead of inline lambdas.”
“Find any v1 fp-go imports in this pull request.”
Requirements
Go 1.24 or newer
A pull request branch to review
Workflow steps
12 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit a2dd5ba. It shows what the files ask for, not the result of running them.
Tool permissions
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Runs code
Shell commands in SKILL.md call:
git
go
gh
From the folder's file list and the shell code blocks in SKILL.md.
Network
Links to these hosts (documentation or services it may open):
pkg.go.dev
From URLs in SKILL.md, links to its own repository left out.
Credentials
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Context cost
fp-go Pull Request Review loads about 6.4k tokens when it runs. Until then it costs about 118 tokens; SKILL.md has 1,564 words of instructions outside code blocks.
Always· name and description, kept in context so the agent knows when to use it
~118
When it runs· the whole SKILL.md, loaded when a task matches
~6.4k
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
Safety
Auto-check passed
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
Download SKILL.mdSave it as .claude/skills/fp-go-pr-review/SKILL.md (or your agent's skills folder).
name
fp-go-pr-review
description
Use this skill when reviewing pull requests for fp-go code (github.com/IBM/fp-go/v2). Trigger on mentions of PR review, code review, pull request validation, fp-go best practices validation, functional programming review, or when the user asks to review changes on a PR branch. This skill validates that changes follow fp-go conventions including data-last composition, point-free style, proper monad usage, lens patterns, and idiomatic functional patterns.
fp-go PR Review
Overview
This skill assists with reviewing pull requests that use the fp-go library (github.com/IBM/fp-go/v2). It validates that code changes follow fp-go best practices and functional programming conventions. Requires Go 1.24+ for generic type alias support.
When to Use This Skill
Reviewing pull requests with fp-go code
Validating that changes follow fp-go best practices
Checking for common fp-go anti-patterns
Ensuring proper functional composition patterns
Verifying correct monad usage and error handling
Review Checklist
1. Import Path Validation
Rule: All imports MUST use github.com/IBM/fp-go/v2/..., never github.com/IBM/fp-go/... (v1).
Also check that import aliases follow the canonical table in the fp-go skill
(R = result, RD = reader, P = predicate, PA = pair, EM = endomorphism,
IOR = ioresult, L = optics/lens, logging unaliased, …). The same letter meaning
two packages across files is a Low finding.
2. Data-Last Principle
Rule: All fp-go operations use data-last. The data being transformed is always the last argument.
Lambdas are acceptable only at the leaves: a struct field accessor (prefer a
generated lens), a setter passed to L.MakeLens, a multi-field formatter, a
side-effecting sink at the program edge (e.g. an HTTP response writer), or a
blocking leaf that must select on ctx.Done(). Everything composed on top of
the leaves should be point-free.
Severity: Medium — impacts readability and maintainability
4. Prefer Result over Either
Rule: Use Result[A] (which is Either[error, A]) when the error type is Go's error. Reserve Either for custom error types.
Check for:
go
// ❌ AVOID - Either with error
func fetchData() E.Either[error, Data] { ... }
// ✅ CORRECT - use Result
func fetchData() R.Result[Data] { ... }
// ✅ CORRECT - Either with custom error type
func validate() E.Either[ValidationError, Data] { ... }
Severity: Medium — Result is more idiomatic for Go errors
5. IO Laziness
Rule: IO values are lazy (IO[A] is func() A). They must be called with () to execute.
Check for:
go
// ❌ WRONG - forgot to execute
result := readConfig("config.json") // returns IO[Config], not Config
// ✅ CORRECT - execute with ()
result := readConfig("config.json")()
// ❌ WRONG - in ReaderIOResult, forgot inner ()
res := pipeline(ctx) // returns func() Result[A], nothing has run yet
// ✅ CORRECT - execute both context and IO
res := pipeline(ctx)() // Result[A] — ONE value
// ❌ WRONG - Result[A] is a single value, not a (value, error) tuple
value, err := pipeline(ctx)()
// ✅ CORRECT - unwrap to idiomatic Go at the boundary
value, err := R.Unwrap(pipeline(ctx)())
Severity: Critical — code won't execute
6. Monad Selection
Rule: Use the simplest monad that covers your needs. Escalate only when necessary.
Check for:
go
// ❌ AVOID - using ReaderIOResult for pure computation
// (also note: in context/readerioresult the context is baked in —
// it is RIO.Of[A] and RIO.Map[A, B], with no environment type parameter)
func processUsers(users []User) RIO.ReaderIOResult[string] {
return F.Pipe1(
RIO.Of(users),
RIO.Map(pureTransform),
)
}
// ✅ CORRECT - pure computation, no monad needed
func processUsers() func([]User) string {
return F.Flow2(
A.FilterMap(toAdultName()),
A.Intercalate(S.Monoid)(","),
)
}
Rule: Use Effect[C, A] for services with typed dependencies. Use ReaderIOResult only when you truly only need context.Context.
Check for:
go
// ❌ AVOID - stuffing deps into context.Context
func fetchUser(id int) RIO.ReaderIOResult[User] {
return func(ctx context.Context) func() R.Result[User] {
db := ctx.Value("db").(DBClient) // runtime type assertion
// ...
}
}
// ✅ CORRECT - typed dependencies with Effect
type Deps struct {
DB DBClient
Logger Logger
}
// Lift an idiomatic function that receives the deps and the context.
// queryUser is func(Deps, context.Context, int) (User, error); deps.DB is compile-time checked.
func fetchUser() EF.Kleisli[Deps, int, User] {
return EF.Eitherize1(queryUser)
}
Effect[Deps, User] IS func(Deps) ReaderIOResult[User]. EF.Asks is only for pure
projections func(Deps) A; feeding it a function that returns a ReaderIOResult
silently produces the nested Effect[Deps, ReaderIOResult[User]] — flag that as High.
Also flag EF.Map(f) and EF.Provide(deps)(eff) without annotations — Map[C, A, B] usually
cannot infer C, and Provide[A, C] cannot infer A through the function it returns. Write
EF.Map[Deps](f) and EF.Provide[string](deps).
Also flag request-scoped data (request IDs, principal, deadlines) placed in C, one wide dependency type used by every function instead of narrow XxxDeps widened with EF.Local, and Provide / RunSync inside library code. See the fp-go-effect skill.
Severity: High — type safety and testability
8. Lifting Go Functions
Rule: Use Eitherize1..EitherizeN to lift Go functions returning (T, error) into Result.
Check for:
go
// ❌ AVOID - manual error handling
func parseNumber(s string) R.Result[int] {
n, err := strconv.Atoi(s)
if err != nil {
return R.Left[int](err) // Left[A] — A is the success type
}
return R.Of(n) // NOT R.Right[error](n); Right[A any](v A)
}
// ✅ CORRECT - use Eitherize
var parseNumber = R.Eitherize1(strconv.Atoi)
// ✅ CORRECT - in pipeline
pipeline := F.Flow2(
R.Eitherize1(strconv.Atoi),
R.Map(N.Mul(2)),
)
Severity: Medium — reduces boilerplate
9. Do-Notation with Lenses
Rule: Use lenses with Bind/ApS instead of manual setter functions.
Check for:
go
// ❌ AVOID - manual setter functions
func setUser(u User) func(State) State {
return func(s State) State { s.User = u; return s }
}
pipeline := F.Pipe1(
RIO.Do(State{}),
RIO.Bind(setUser, fetchUser),
)
// ✅ CORRECT - use lens
var userLens = L.MakeLens(
func(s State) User { return s.User },
func(s State, u User) State { s.User = u; return s },
)
pipeline := F.Pipe1(
RIO.Do(State{}),
RIO.Bind(userLens.Set, fetchUser),
)
// ✅ EVEN BETTER - use code generation
//go:generate go run github.com/IBM/fp-go/v2 lens --dir . --filename gen_lens.go
// fp-go:Lens
type State struct {
User User
}
// Then use generated lens
lenses := MakeStateLenses()
pipeline := F.Pipe1(
RIO.Do(State{}),
RIO.Bind(lenses.User.Set, fetchUser),
)
Severity: Medium — maintainability and consistency
10. Bind vs ApS
Rule: Use Bind when the step depends on accumulated state; use ApS when steps are independent.
Check for:
go
// ❌ WRONG - using Bind when steps are independent
pipeline := F.Pipe2(
RIO.Do(Summary{}),
RIO.Bind(userLens.Set, func(_ Summary) RIO.ReaderIOResult[User] {
return fetchUser(42) // doesn't use state
}),
RIO.Bind(weatherLens.Set, func(_ Summary) RIO.ReaderIOResult[Weather] {
return fetchWeather("NYC") // doesn't use state
}),
)
// ✅ CORRECT - use ApS for independent steps
pipeline := F.Pipe2(
RIO.Do(Summary{}),
RIO.ApS(userLens.Set, fetchUser(42)),
RIO.ApS(weatherLens.Set, fetchWeather("NYC")),
)
// ✅ CORRECT - ApS for the independent first step, Bind for the dependent one
pipeline := F.Pipe2(
RIO.Do(Pipeline{}),
RIO.ApS(userLens.Set, fetchUser(42)),
RIO.Bind(configLens.Set, F.Flow2(userLens.Get, fetchConfigForUser)),
)
Severity: Medium — semantic clarity
11. TraverseArray Usage
Rule: Use TraverseArray to process slices monadically, not manual loops with error accumulation.
Check for:
go
// ❌ AVOID - manual loop with error handling
func fetchAll(ids []int) RIO.ReaderIOResult[[]User] {
return func(ctx context.Context) func() R.Result[[]User] {
return func() R.Result[[]User] {
users := make([]User, 0, len(ids))
for _, id := range ids {
user, err := R.Unwrap(fetchUser(id)(ctx)())
if err != nil {
return R.Left[[]User](err)
}
users = append(users, user)
}
return R.Of(users)
}
}
}
// ✅ CORRECT - use TraverseArray, point-free (return the Kleisli, don't take ids)
func fetchAll() RIO.Kleisli[[]int, []User] {
return RIO.TraverseArray(fetchUser)
}
Severity: High — idiomatic functional pattern
12. Logging Side Effects
Rule: Log with the Tap* operators, which run the side effect and pass the original value (or error) through unchanged. Prefer structured TapSLog; use TapIOK(IO.Logf…) for printf-style logs and LogEntryExit for entry/exit logs. See the fp-go-logging skill.
Check for:
go
// ❌ AVOID - breaking the pipeline for logging
pipeline := F.Pipe1(
fetchUser(42),
RIO.Chain(func(user User) RIO.ReaderIOResult[User] {
log.Printf("Fetched user: %v", user)
return RIO.Of(user)
}),
)
// ✅ CORRECT - structured logging with TapSLog (logs value or error)
pipeline := F.Pipe1(
fetchUser(42),
RIO.TapSLog[User]("User fetched"),
)
// ✅ CORRECT - printf-style logging with TapIOK
pipeline := F.Pipe1(
fetchUser(42),
RIO.TapIOK(IO.Logf[User]("Fetched user: %v")),
)
Also flag ChainFirstIOK used for logging (Low: works, but TapIOK states the intent) and slog.Info inside Map (Medium: a side effect in a pure function that also bypasses the context logger).
Severity: Low — code quality
13. Prefer Functions over Variables
Rule: Wrap pipeline results in functions, not package-level vars.
Check for:
go
// ❌ WRONG - var is allocated even if never called
var processUser = F.Flow2(getName, strings.ToUpper)
// ✅ CORRECT - zero cost until called
func processUser() func(User) string {
return F.Flow2(getName, strings.ToUpper)
}
The rule targets composed pipelines (Pipe/Flow results). A var is fine for lenses and for a single pre-bound helper such as var parseNumber = R.Eitherize1(strconv.Atoi) or var getHost = hostLens.Get (same rule as the fp-go-pipe-flow skill).
Severity: Low — performance and dead code elimination
14. Type Parameter Order
Rule: Non-inferrable type parameters come first, so an explicit annotation only ever needs the leading prefix.
Which params are non-inferrable differs per package — check the signature rather than assuming:
go
// option / result / ioresult: Map[A, B](f func(A) B) — BOTH inferable from f
O.Map(toLength) // ✅ preferred, no annotation at all
O.Map[string, int](toLength) // ✅ legal but redundant (note the order: A then B)
// Ap[B, A](fa M[A]) — B is not recoverable from fa, so it leads
O.Ap[int](fa) // ✅
// either / reader / readerio*: the error or environment type leads
E.Map[error](f) // ✅ either.Map[E, A, B]
RD.Map[context.Context](f) // ✅ reader.Map[R, A, B]
// effect: C leads and is often not inferable
EF.Map[Deps](f) // ✅
EF.Provide[string](deps) // ✅ Provide[A, C] cannot infer A through its result
Flag an annotation that is in the wrong order (it will not compile) or one that
restates what the compiler already infers.
Severity: Low — compilation errors or verbosity
15. Lens Composition
Rule: Use Compose/ComposeRef for nested struct access, not manual chaining.
Rule: Functions passed to Map, Chain, Filter, etc. must be pure — they must not mutate variables captured from an outer scope, and lens setters must not mutate shared slice/map fields in place.
Check for:
go
// ❌ WRONG - closure mutates a captured slice
var acc []string
A.Map(func(u User) User {
acc = append(acc, u.Name) // hidden side effect
return u
})
// ✅ CORRECT - derive a new value, no captured mutation
names := F.Pipe1(users, A.Map(getName))
// ❌ WRONG - lens setter mutates a shared slice in place
// append may reuse the original backing array (shallow struct copy)
func(u User, t []string) User { u.Tags = append(u.Tags, t...); return u }
// ✅ CORRECT - assign a freshly built value
func(u User, t []string) User { u.Tags = t; return u }
Severity: High — a mutating closure silently defeats fp-go's guarantees and breaks under TraverseArray/concurrency.
17. Context Access and Scoping
Rule: Read context.Context values with AskValue, and scope values, timeouts and deadlines with the WithValue / WithTimeout / WithDeadline operators (or Local). Do not type-assert ctx.Value or derive contexts by hand inside pipelines. The operators exist in context/readerio, context/readerresult, context/readerioresult, context/statereaderioresult and idiomatic/context/readerresult.
Check for:
go
// ❌ WRONG - panics if the key is missing or has another type; plain string key
getUser := RIO.FromReader(func(ctx context.Context) string {
return ctx.Value("user").(string)
})
// ✅ CORRECT - typed key, Option result, caller decides what "missing" means
type ctxKey string
const userKey ctxKey = "user"
getUser := F.Pipe1(RIO.AskValue[string](userKey), RIO.Map(O.GetOrElse(LZ.Of("anonymous"))))
// ❌ WRONG - hand-derived context; cancel discarded -> leaked timer
RIO.Local[A](func(ctx context.Context) ContextCancel {
tctx, _ := context.WithTimeout(ctx, 5*time.Second)
return pair.MakePair(func() {}, tctx)
})
// ❌ WRONG - scoping done outside the pipeline, by hand
ctx, cancel := context.WithTimeout(context.WithValue(ctx, userKey, u), 5*time.Second)
defer cancel()
res := pipeline(ctx)()
// ✅ CORRECT - scoping as operators; cancel always released
res := F.Pipe2(
pipeline,
RIO.WithTimeout[A](5*time.Second),
RIO.WithValue[A](userKey, u),
)(ctx)()
// ❌ WRONG - Unpack + defer just to install a logger
cancel, lctx := pair.Unpack(logging.WithLogger(l)(ctx)); defer cancel()
// ✅ CORRECT - WithLogger already has Local's shape
F.Pipe1(pipeline, RIO.Local[A](logging.WithLogger(l)))
Also flag:
string or other exported key types ("user", int) — use an unexported type ctxKey string
dependencies (DB, config, clients) stored in the context — see §7, use Effect
outside pipelines, context.WithValue(ctx, k, v) where CR.WithValue[V](k)(v)(ctx) from context/reader would keep code consistent (Low)
Severity: High for panicking assertions and leaked cancel functions; Medium for hand-rolled scoping that has an operator equivalent.
Review Process
Show full SKILL.md (637 more words)Show less
Step 1: Obtain Git Diff
Get the changes on the PR branch relative to main:
bash
git diff main...HEAD
To list only changed file paths:
bash
git diff --name-only main...HEAD
For a GitHub PR, fetch it first:
bash
gh pr checkout <PR-number>
git diff main...HEAD
Step 2: Analyze Changes
First, confirm the branch compiles: run go build ./... and go vet ./... on the
checked-out branch. Report any build or vet failure as a Critical finding —
there is no point reviewing composition style on code that does not compile, and
most fp-go-specific mistakes (wrong leading type parameter, data-first vs
data-last argument order, missing trailing ()) surface here.
fp-go-pattern-matching — replacing switch / if-else chains with point-free case lists
fp-go-effect — Effect[C, A] with typed dependencies in C: capability interfaces, Local, testing with fakes (see §7)
Automated Checks
When reviewing, automatically check for:
✅ All imports use v2 path
✅ No data-first function calls
✅ IO values are executed with ()
✅ Result used instead of Either[error, A]
✅ Point-free style: no lambdas above the leaves; Eitherize instead of hand-written closures; ApS instead of state-ignoring Bind
✅ Appropriate monad selection
✅ Lenses used in do-notation
✅ Bind vs ApS used correctly
✅ TraverseArray for slice processing
✅ Logging via TapSLog / TapIOK / LogEntryExit (see the fp-go-logging skill)
✅ No hidden mutation in Map/Chain closures or lens setters
✅ Context values read with AskValue; values/timeouts scoped with WithValue/WithTimeout/WithDeadline/Local (no ctx.Value(k).(T), no discarded cancel funcs)
✅ Branch compiles (go build ./...) and passes go vet ./...
✅ Import aliases follow the canonical table (see the fp-go skill)
Output Format
Provide a summary with:
Overall Assessment: Pass/Needs Changes/Blocked
Critical Issues: Count and list
High Priority Issues: Count and list
Medium Priority Issues: Count and list
Low Priority Issues: Count and list
Positive Observations: What was done well
Recommendations: Suggested improvements
Example Summary
markdown
## PR Review Summary
**Overall Assessment**: Needs Changes
### Critical Issues (2)
- ❌ Using v1 import path in `user/handler.go:5`
- ❌ Missing IO execution in `config/loader.go:42`
### High Priority Issues (1)
- ⚠️ `ctx.Value("user").(string)` type assertion instead of `AskValue` in `api/auth.go:31`
### Medium Priority Issues (4)
- 💡 Manual error handling instead of Eitherize in `api/client.go:78`
- 💡 Inline lambda instead of point-free in `user/service.go:23`
- 💡 Using ReaderIOResult for pure computation in `utils/format.go:15`
- 💡 Manual setter instead of lens in `state/pipeline.go:56`
### Low Priority Issues (1)
- 📝 Inconsistent import alias in `handler/http.go:8`
### Positive Observations
- ✅ Excellent use of TraverseArray for parallel requests
- ✅ Proper Effect usage with typed dependencies
- ✅ Good lens composition for nested struct access
### Recommendations
1. Update all imports to v2 path
2. Add trailing `()` to execute IO values
3. Consider using `R.Eitherize1` for Go function lifting
4. Refactor pure computations to use Flow instead of ReaderIOResult
fp-go Pull Request Review next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
fp-go Pull Request Review compared with similar skills
Runs a loop on a GitHub pull request: fetch review state, triage comments into actions, implement them and resolve threads, repeating until nothing actionable is left.
Fetches a pull request's canonical review state as JSON, validates it, and renders markdown, a text summary and triage target files from it using bundled scripts.
Checks that a pull request's title and description match its implementation and reviews the code for Garnet best practices, reporting findings without posting them.
Reviews a fastlane pull request against its linked issue and the project guides, separating blocking from non-blocking findings and handling vulnerabilities privately.
Covers handling Go's context.Context idiomatically in fp-go code: reading and scoping context through operators, timeouts, cancellation and converting ctx-first functions.
Teaches an agent to write fp-go v2 services with the Effect type, carrying dependencies in its type parameter instead of in context.Context or parameters.
Adds logging to fp-go functional pipelines with Tap operators, entry and exit logs and error context, so that logging never changes the value or error flowing through.
Reviews pull requests that use the fp-go library against its conventions: v2 imports, data-last arguments, point-free style, Result over Either and idiomatic monads. 24 or newer for generic type aliases. Imports must use v2 and never v1, flagged critical because the versions are incompatible, and import aliases must follow the canonical table so one letter never stands for two packages.
When should I use fp-go Pull Request Review?
fp-go Pull Request Review fits situations like: reviewing a pull request that adds fp-go code; checking changes for data-first calls or v1 imports; reviewing functional composition and monad usage in Go.
How do I install fp-go Pull Request Review in Claude Code?
Run `npx skills add IBM/fp-go --skill fp-go-pr-review -a claude-code`. Or copy the skill folder (skills/fp-go-pr-review in IBM/fp-go) into .claude/skills/fp-go-pr-review in your project. Claude Code loads it when a task matches its description.
How do I install fp-go Pull Request Review in Codex?
Run `npx skills add IBM/fp-go --skill fp-go-pr-review -a codex`. Or copy the skill folder (skills/fp-go-pr-review in IBM/fp-go) into .agents/skills/fp-go-pr-review in your project. Codex loads it when a task matches its description.
Can I use fp-go Pull Request Review in Cursor, Gemini CLI or GitHub Copilot?
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add IBM/fp-go --skill fp-go-pr-review -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/fp-go-pr-review, .gemini/skills/fp-go-pr-review, .github/skills/fp-go-pr-review and .opencode/skills/fp-go-pr-review in your project.
What does fp-go Pull Request Review need to run?
Going by SKILL.md and its folder, fp-go Pull Request Review needs the command-line tools its instructions call (git, go and gh). Our summary lists: Go 1.24 or newer; A pull request branch to review.
Does fp-go Pull Request Review access the network?
SKILL.md names 1 domain. As links in the text: pkg.go.dev. This is read from the text; nothing was executed.
Is fp-go Pull Request Review safe to install?
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
What licence does fp-go Pull Request Review use?
fp-go Pull Request Review is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
How many tokens does fp-go Pull Request Review use?
About 6.4k tokens (SKILL.md is roughly 25k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
What are the alternatives to fp-go Pull Request Review?
Skills that share tags, products or a category with fp-go Pull Request Review: PR Babysitter (openinterpreter/openinterpreter, 69k stars), GitHub Review Iteration (prisma/orm, 48k stars), PR Review State Fetch (prisma/orm, 48k stars) and PR Finalize Review (microsoft/garnet, 12k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Who maintains fp-go Pull Request Review?
IBM (a GitHub organization, an official publisher) maintains it in IBM/fp-go, which has 2,031 GitHub stars. The repository holds 10 skills in this directory. The repository was last updated on October 11, 2026.
Source: IBM/fp-go on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.