Effect Claudecode banner
mpsuesser mpsuesser

Effect Claudecode

Development community

Description

Effect v4 bindings for Claude Code's plugin primitives — hooks, skills, settings, MCP servers, frontmatter

Installation

This entry records only its repository, not the path inside it, so there is no exact command to give. Open the source below and copy the folder into ~/.claude/skills/, or the file into ~/.claude/agents/.

README

effect-claudecode

Write [Claude Code](https://code.claude.com) plugins — hooks, skills, subagents, commands, MCP servers — with [Effect v4](https://effect.website).

Install

npm install effect-claudecode effect@4.0.0-beta.80 @effect/platform-node-shared@4.0.0-beta.80
bun add effect-claudecode effect@4.0.0-beta.80 @effect/platform-node-shared@4.0.0-beta.80

Before / After

A vanilla Claude Code hook that rewrites `npm test` to `bun run test`:

// hooks/rewrite-test.js — vanilla Node.js
let data = '';
process.stdin.on('data', (chunk) => (data += chunk));
process.stdin.on('end', () => {
  const input = JSON.parse(data);
  const command = input.tool_input?.command ?? '';
  const output = command.startsWith('npm test')
    ? { continue: true, hookSpecificOutput: {
        hookEventName: 'PreToolUse',
        updatedInput: { command: command.replace('npm test', 'bun run test') },
        permissionDecision: 'allow',
        permissionDecisionReason: 'This workspace runs tests through Bun.'
      }}
    : { continue: true };
  process.stdout.write(JSON.stringify(output));
  process.exit(0);
});

The same hook with effect-claudecode:

import * as Effect from 'effect/Effect';
import * as Str from 'effect/String';
import { Hook } from 'effect-claudecode';

const hook = Hook.PreToolUse.onTool({
  toolName: 'Bash',
  handler: ({ tool }) =>
    Effect.succeed(
      Str.startsWith('npm test')(tool.command)
        ? Hook.PreToolUse.allowWithUpdatedInput(
            { command: Str.replace('npm test', 'bun run test')(tool.command) },
            'This workspace runs tests through Bun.'
          )
        : Hook.PreToolUse.allow()
    )
});

Hook.runMain(hook);

Typed tool payloads, decision constructors, correct exit-code semantics — no stdin plumbing, no manual JSON, no `process.exit`.

What You Can Build

Detect when Claude is stuck in a loop

Every Claude Code user has watched Claude read the same file three times in a