Automated summary
Guides the choice between Go standard library collection helpers and github.com/samber/lo when writing or refactoring collection and pointer helper code in OpenMeter.
Strengths
- Puts slices and maps first before recommending lo helpers.
- Maps common lo helpers to slice, map, pointer, and error-returning transformations.
- Clarifies import conventions and which lo subpackages to avoid by default.
- Calls out the pinned lo version used by OpenMeter.
Limitations
- Narrowly scoped to OpenMeter and lo v1.53.0.
- Does not cover lo/parallel, lo/mutable, or lo/it in depth.
- Offers guidance rather than full refactoring examples or performance benchmarks.
Use when writing or refactoring Go collection code in OpenMeter and deciding whether standard library helpers or samber/lo express the operation more clearly.
Avoid when working outside Go/OpenMeter or when a plain loop is clearer than any collection helper.
Security analysis
SafeThe skill is a Go coding-reference guide for using standard library collection helpers and github.com/samber/lo. It contains no destructive commands, credential access, exfiltration, obfuscated payloads, or safety-disabling instructions. Bash is listed as an allowed tool but the skill itself does not instruct its use for risky operations.
No concerns found
How this analysis is madeExamples
Refactor this Go code to use slices.Clone instead of append([]T(nil), s...) and lo.ToPtr for the pointer fields, keeping imports explicit.In OpenMeter, should I use lo.GroupBy or lo.SliceToMap to group usage events by meter ID and collect their IDs? Rewrite the function with the clearer helper.Replace this hand-written map transformation with lo.MapEntries or lo.MapValues as appropriate, and explain why the chosen helper is clearer.name: samber-lo description: Use when writing or refactoring Go collection/pointer helper code in OpenMeter, especially when choosing between standard library slices/maps helpers and github.com/samber/lo for cloning, copying, equality, sorting, pointer literals, slice-to-map transforms, map keys/values, mapping, filtering, grouping, uniqueness, set-like conversions, and map entry transformations. user-invocable: true argument-hint: "[collection transformation or lo helper question]" allowed-tools: Read, Edit, Write, Bash, Grep, Glob
samber/lo
Use standard library collection helpers first when they express the operation directly, and use github.com/samber/lo for small, local collection transformations when it makes the intent clearer than a hand-written loop. OpenMeter pins github.com/samber/lo v1.53.0 in go.mod.
Imports
import "maps"
import "slices"
import "github.com/samber/lo"
Do not use dot imports. Do not reach for lo/parallel, lo/mutable, or lo/it unless the surrounding package already uses that subpackage or the task explicitly needs it.
Standard Library First
Prefer slices for operations the standard library already names clearly:
slices.Clone(s)for defensive slice copies instead ofappend([]T(nil), s...).slices.Contains(s, v)for membership checks on short or already-available slices.slices.Sort,slices.SortFunc, andslices.SortStableFuncbefore comparing, logging, serializing, or asserting on order.slices.Equalandslices.EqualFuncfor equality checks.slices.Concat(a, b, c)for concatenating known slices.slices.Compactafter sorting when normalizing a slice.
Prefer maps for direct map operations:
maps.Clone(m)for defensive copies.maps.Copy(dst, src)when merging maps.maps.Equalandmaps.EqualFuncfor equality checks.maps.Keys(m)andmaps.Values(m)when the iterator result is acceptable; collect or sort when a slice is required or order matters.
Prefer lo.ToPtr(...), lo.FromPtr(...), and lo.FromPtrOr(...) for pointer literals and pointer defaults. Avoid local wrappers such as ptr, loPtr, must, or loMust.
Common Helpers
For slice transforms:
lo.Map(items, func(item T, index int) R)converts[]Tto[]R.lo.Filter(items, func(item T, index int) bool)keeps matching items.lo.FilterMap(items, func(item T, index int) (R, bool))filters and maps in one pass.lo.Uniq(items)andlo.UniqBy(items, func(item T) K)remove duplicates.lo.GroupBy(items, func(item T) K)returnsmap[K][]T.lo.GroupByMap(items, func(item T) (K, V))returnsmap[K][]V.
For slice-to-map work:
lo.KeyBy(items, func(item T) K)returnsmap[K]T.lo.SliceToMap(items, func(item T) (K, V))returnsmap[K]V;lo.Associateis the same operation, but preferSliceToMapfor readability.lo.FilterSliceToMap(items, func(item T) (K, V, bool))returnsmap[K]Vwhile skipping items.lo.Keyify(items)returnsmap[T]struct{}for set-like membership.
For map work:
lo.Keys(m)andlo.Values(m)return slices.lo.UniqKeys(m1, m2)andlo.UniqValues(m1, m2)combine maps while removing duplicates.lo.MapKeys(m, func(value V, key K) R)changes key type while preserving values.lo.MapValues(m, func(value V, key K) R)changes values while preserving keys.lo.MapEntries(m, func(key K, value V) (K2, V2))changes both keys and values.lo.MapToSlice(m, func(key K, value V) R)converts a map to a slice.lo.FilterMapToSlice(m, func(key K, value V) (R, bool))filters and maps a map into a slice.lo.PickBy,lo.OmitBy,lo.FilterKeys, andlo.FilterValuesare useful when only part of a map is needed.
Use *Err variants such as MapErr, KeyByErr, GroupByMapErr, MapValuesErr, or MapToSliceErr when the callback can fail and the first error should stop the transform.
For slice-wide invariants where the exact offending element is not important, prefer collecting distinct values with lo.Map plus lo.Uniq and validating cardinality over stateful "first seen value" loops.
Correctness Notes
- Duplicate keys in
KeyBy,SliceToMap,MapKeys, andMapEntriesoverwrite earlier entries; the last value wins. - Map iteration order is not stable. Sort keys or results before comparing, logging, serializing, or asserting on order.
- Callback argument order differs by helper: slice helpers usually pass
(item, index), map helpers usually pass(value, key)forMapKeys/MapValuesand(key, value)forMapEntries/MapToSlice. - Prefer a plain
forloop when the transform has branching business rules, context-aware calls, transaction-sensitive operations, side effects, or multi-step error handling. - Keep code inline for tiny transformations; do not add pass-through wrappers around
lohelpers unless the wrapper name captures a domain rule that is not obvious from the helper call.
Examples
ids := lo.Map(customers, func(customer customer.Customer, _ int) string {
return customer.ID
})
byID := lo.KeyBy(customers, func(customer customer.Customer) string {
return customer.ID
})
namesByID := lo.SliceToMap(customers, func(customer customer.Customer) (string, string) {
return customer.ID, customer.Name
})
activeNamesByID := lo.FilterSliceToMap(customers, func(customer customer.Customer) (string, string, bool) {
return customer.ID, customer.Name, customer.Active
})
externalIDs := lo.Keys(externalIDByCustomerID)
apiByID := lo.MapValues(customerByID, func(customer customer.Customer, _ string) api.Customer {
return mapCustomerToAPI(customer)
})
Design-to-Dev Specification Writer
Development
Translate your mockups into technical specifications for developers.
Exports & Barrel Files
Development
Defines conventions for module exports and barrel files: named exports only, no flat wildcards (except `export * as Name` for compound components), sectioned comments, types alongside values, and one export line per source file. Helps maintain consistent, tree-shakeable exports in portal apps using Turbopack or similar bundlers.
Write an Agent Skill
Development
Step-by-step guide to create a structured Agent Skill for coding agents, including directory structure, SKILL.md format, and design principles.