agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling…
Migrate a single oRPC procedure from classic async handler to Effect-backed implementation. Use when converting procedures one at a time to maintain incremental, reviewable changes.
$ npx -y skills add humanlayer/humanlayer --skill migrate-orpc-to-effect --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/migrate-orpc-to-effectContext preview
The summary Claude sees to decide when to auto-load this skill.
Migrate a single oRPC procedure from classic async handler to Effect-backed implementation. Use when converting procedures one at a time to maintain incremental, reviewable changes.
name: migrate-orpc-to-effect description: Migrate a single oRPC procedure from classic async handler to Effect-backed implementation. Use when converting procedures one at a time to maintain incremental, reviewable changes. version: "1.1.0"
Converts a single classic oRPC procedure to an Effect-backed implementation while preserving route shape, response contract, and authorization semantics.
**IMPORTANT: Always check the source of truth for available services:**
# Check AppRuntimeServices type for available Effect services cat apps/riptide-api/src/effects/app-runtime.ts | head -50
Only migrate procedures that use services available in `appRuntime`. The `AppRuntimeServices` type in `apps/riptide-api/src/effects/app-runtime.ts` is the authoritative list.
**Key services to look for:**
**If a procedure uses a classic service not in `AppRuntimeServices`, do NOT migrate it.**
Before starting, verify the target procedure is eligible:
# 1. Check what services the procedure uses rg 'services\.' <file> # 2. Check what Effect services are available in the runtime cat apps/riptide-api/src/effects/app-runtime.ts | grep -A20 'AppRuntimeServices' # 3. Confirm procedure hasn't already been migrated rg "from 'effect'" <file> # If matches, procedure is already migrated
If the procedure uses any service from `context.services` that doesn't have a corresponding Effect service in `AppRuntimeServices`, **do NOT migrate it**.
Stripe procedures are eligible only when they can call the public Effect `StripeService` from `apps/riptide-api/src/effects/services/stripe/stripe.service.ts`. Do not call the Stripe TypeScript SDK directly from a migrated oRPC procedure. Load and follow the `effect-program-design` skill for Stripe migrations. `STRIPE_SECRET_KEY` may only be consumed through `Config.redacted` in the Stripe HTTP adapter and must never be printed, inspected, or threaded through procedure code. `kv` remains unavailable; there is no generic `KvService` for migrated procedures.
Read the source file and understand:
Map the classic base to its Effect equivalent:
| Classic Base | Effect Base | |--------------|-------------| | `apiBaseOrgRequired` | `effectOrpcBaseOrganizationRequired` | | `apiBasePublic` | `effectOrpcBasePublic` | | `apiBaseForOrganizationAdmin` | `effectOrpcBaseForOrganizationAdmin` | | `daemonBase` | `effectOrpcDaemonBase` |
All Effect bases are exported from `apps/riptide-api/src/orpc/effect-base.ts`.
Create a new file with `.effect.ts` suffix alongside the original:
apps/riptide-api/src/orpc/api/comments/delete.ts # original apps/riptide-api/src/orpc/api/comments/delete.effect.ts # new Effect version
Follow the golden pattern structure:
import { /* drizzle tables */ } from '@humanlayer/db/tables/...'
import { /* drizzle operators */ } from 'drizzle-orm'
import { Effect } from 'effect'
import { mapPostgresErrorToResponse } from '../../../effects/services/postgres/error-mapping'
import { getTransactionId } from '../../../effects/services/postgres/helpers'
import { PostgresDb } from '../../../effects/services/postgres/postgres-db.service'
import { Sentry } from '../../../instrument'
import { effectOrpcBaseOrganizationRequired } from '../../effect-base'
export const deleteCommentEffectProcedure = effectOrpcBaseOrganizationRequired.comments.delete
.effect(function* ({ input, context, errors }) {
// 1. Yield services from runtime
const postgres = yield* PostgresDb
// 2. Extract auth context
const { userId, organizationId } = context.auth
// 3. Implement logic using Effect patterns
const result = yield* postgres.transaction((tx) =>
Effect.gen(function* () {
// Query using tx.query() wrapper
const [comment] = yield* tx.query(
tx.client
.select()
.from(artifactComments)
.where(eq(artifactComments.id, input.commentId))
.limit(1)
)
// Fail with oRPC errors using Effect.fail
if (!comment) {
return yield* Effect.fail(
errors.NOT_FOUND({ data: { message: 'Comment not found' } })
)
}
// Continue with business logic...
const transactionId = yield* getTransactionId(tx)
return { success: true, transactionId }
})
).pipe(
// Log errors for observability
Effect.tapError((e) => Effect.logError(e)),
// Capture to Sentry
Effect.tapError((e) => Effect.sync(() => Sentry.captureException(e))),
// Map tagged Postgres errors to oRPC responses
Effect.catchTags({
PostgresDbQueryError: (error) => mapPostgresErrorToResponse(error, errors),
PostgresDbTransactionError: (error) => mapPostgresErrorToResponse(error, errors),
})
)
// 4. Log success with structured context
yield* Effect.logInfo('Comment deleted').pipe(HumanLayer runs coding agents (Claude Code, Codex, OpenCode, Pi) on your machines and lets your team steer them from one place: tasks, sessions, plans, and reviews, synced between a desktop app, a web app, and a daemon on each host. This repo holds all of it.
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling…
Rewrites ambiguous English into ASD-STE100 style — one meaning per word, active voice, simple tense, short sentences. Use when…
Use for 1) inspecting PR state, 2) reading review threads, or 3) debugging CI failures. Otherwise use the gh CLI.
Bump the base version of one or more packages (riptide-native, cli, linear-cli, rpi-plugin) on a PR - updates every synced file,…
Diff call stacks across git commits for agentic code review (22 languages). Run `calldiff --help` for usage details.
Use this to skill to write shell scripts or run shell commands to automate tasks in the browser or otherwise use Chrome DevTools…