Claude Code Plugins

Community-maintained marketplace

Feedback

Builtin Developer

@sunholo-data/ailang
8
0

Guides development of AILANG builtin functions. Use when user wants to add a builtin function, register new builtins, or understand the builtin system. Reduces development time from 7.5h to 2.5h (-67%).

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name Builtin Developer
description Guides development of AILANG builtin functions. Use when user wants to add a builtin function, register new builtins, or understand the builtin system. Reduces development time from 7.5h to 2.5h (-67%).

Builtin Developer

Add new builtin functions to AILANG using the modern registry system (M-DX1).

Quick Start

Development time: ~2.5 hours (down from 7.5h with legacy system)

Most common workflow:

  1. Register builtin with metadata (~30 min)
  2. Write hermetic tests (~1 hour)
  3. Validate and inspect (~30 min)
  4. Runtime auto-wires (already done!)

When to Use This Skill

Invoke this skill when:

  • User wants to add a new builtin function
  • User asks about builtin registration process
  • User needs to understand the builtin system
  • User wants to validate or inspect builtins
  • User asks "how do I add a builtin?"

System Overview

Status: 🎉 M-DX1 COMPLETE (Oct 2025) - 52 builtins migrated, fully documented

Key Benefits:

  • 67% faster: 2.5h instead of 7.5h
  • 1 file instead of 4: Single-point registration
  • 71% less code: Type Builder DSL reduces boilerplate
  • Automatic wiring: Registry connects to runtime/link
  • Hermetic tests: MockEffContext with HTTP/FS mocking

Components:

  • Central Registry (internal/builtins/spec.go) - Single registration point
  • Type Builder DSL (internal/types/builder.go) - Fluent type construction
  • Test Harness (internal/effects/testctx/) - Hermetic testing helpers
  • CLI Commands - Validation and inspection tools

Available Scripts

scripts/validate_builtins.sh

Validate all builtins in the registry.

Usage:

.claude/skills/builtin-developer/scripts/validate_builtins.sh

What it checks:

  • All builtins are registered
  • Proper metadata structure
  • Type signatures valid
  • Test coverage exists

scripts/check_builtin_health.sh

Run ailang doctor and list commands.

Usage:

.claude/skills/builtin-developer/scripts/check_builtin_health.sh

Workflow

Step 1: Register the Builtin (~30 min)

Create or edit module file (e.g., internal/builtins/string.go):

// internal/builtins/string.go
func init() {
    registerMyBuiltin()
}

func registerMyBuiltin() {
    RegisterEffectBuiltin(BuiltinSpec{
        Module:  "std/string",
        Name:    "_str_reverse",
        NumArgs: 1,
        IsPure:  true,        // or false with Effect: "IO"
        Type:    makeReverseType,
        Impl:    strReverseImpl,
        Metadata: &BuiltinMetadata{
            Description: "Reverse a string (Unicode-aware)",
            Params: []ParamDoc{
                {Name: "s", Description: "String to reverse"},
            },
            Returns: "Reversed string",
            Examples: []Example{
                {Code: `_str_reverse("hello")`, Description: "Returns \"olleh\""},
            },
            Since:     "v0.3.15",
            Stability: StabilityStable,
            Tags:      []string{"string", "reverse", "unicode"},
            Category:  "string",
        },
    })
}

func makeReverseType() types.Type {
    T := types.NewBuilder()
    return T.Func(T.String()).Returns(T.String())
}

func strReverseImpl(ctx *effects.EffContext, args []eval.Value) (eval.Value, error) {
    str := args[0].(*eval.StringValue).Value
    runes := []rune(str)
    for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
        runes[i], runes[j] = runes[j], runes[i]
    }
    return &eval.StringValue{Value: string(runes)}, nil
}

Key points:

  • Use RegisterEffectBuiltin() in init()
  • Use Type Builder DSL for type construction
  • Include complete metadata (description, params, examples, tags)
  • Set IsPure: true for pure functions, or Effect: "IO" for effects

See: resources/type_builder_examples.md for type patterns

Step 2: Write Hermetic Tests (~1 hour)

Add tests in internal/builtins/register_test.go:

func TestStrReverse(t *testing.T) {
    ctx := testctx.NewMockEffContext()

    tests := []struct {
        input    string
        expected string
    }{
        {"hello", "olleh"},
        {"", ""},
        {"🎉", "🎉"},
    }

    for _, tt := range tests {
        result, err := strReverseImpl(ctx, []eval.Value{
            testctx.MakeString(tt.input),
        })
        assert.NoError(t, err)
        assert.Equal(t, tt.expected, testctx.GetString(result))
    }
}

Test Harness helpers:

  • testctx.NewMockEffContext() - Create test context
  • testctx.MakeString(), MakeInt(), MakeRecord() - Create test values
  • testctx.GetString(), GetInt(), GetRecord() - Extract values

For HTTP/FS effects:

ctx := testctx.NewMockEffContext()
ctx.GrantAll("Net")  // Grant Net capability
ctx.SetHTTPClient(server.Client())  // Use test server

See: resources/testing_patterns.md for more examples

Step 3: Validate and Inspect (~30 min)

Run validation:

# Validate all builtins
ailang doctor builtins

# List all builtins by module
ailang builtins list --by-module

# Check for orphaned builtins (migration safety)
ailang builtins check-migration

Run tests:

# Test specific builtin
go test -v internal/builtins -run TestStrReverse

# Test all builtins
make test

Test in REPL:

ailang repl
> :type _str_reverse
string -> string

> _str_reverse("hello")
"olleh" : string

Step 4: Runtime Wiring (Automatic!)

No manual wiring needed! The registry automatically:

  • ✅ Registers with evaluator (internal/eval)
  • ✅ Adds to type environment (internal/types)
  • ✅ Links to runtime (internal/runtime)
  • ✅ Generates module interface (internal/link)

Feature flag removed in v0.3.10 - New registry is now the default.

Key Components

Central Registry

Location: internal/builtins/spec.go

Features:

  • Single registration point with RegisterEffectBuiltin()
  • Compile-time validation (arity, types, impl, effects)
  • Freeze-safe (no registration after init)
  • 52 builtins migrated

Type Builder DSL

Location: internal/types/builder.go

Reduces type construction from 35 lines → 10 lines (-71%)

Available methods:

T := types.NewBuilder()

// Primitive types
T.String()
T.Int()
T.Float()
T.Bool()
T.Unit()

// Complex types
T.List(elementType)
T.Record(fields...)
T.Tuple(types...)
T.Con("TypeName")
T.Var("α")

// Function types
T.Func(arg1, arg2, ...).Returns(returnType).Effects("IO", "FS")

// Type applications
T.App("Result", okType, errType)

See: resources/type_builder_examples.md

Test Harness

Location: internal/effects/testctx/

Value constructors:

  • MakeString(s string) → StringValue
  • MakeInt(i int) → IntValue
  • MakeFloat(f float64) → FloatValue
  • MakeBool(b bool) → BoolValue
  • MakeList([]Value) → ListValue
  • MakeRecord(map[string]Value) → RecordValue

Value extractors:

  • GetString(Value) → string
  • GetInt(Value) → int
  • GetFloat(Value) → float64
  • GetBool(Value) → bool
  • GetList(Value) → []Value
  • GetRecord(Value) → map[string]Value

Effect mocking:

  • ctx.GrantAll(effect) - Grant capabilities
  • ctx.SetHTTPClient(client) - Mock HTTP
  • ctx.SetFS(fs) - Mock filesystem

Validation & Inspection

Commands:

ailang doctor builtins              # Health checks
ailang builtins list                # List all builtins
ailang builtins list --by-module    # Group by module
ailang builtins list --by-effect    # Group by effect
ailang builtins check-migration     # Check for orphaned builtins

6 validation rules:

  1. Type function exists and valid
  2. Implementation function exists
  3. Arity matches NumArgs
  4. Effect consistency (IsPure vs Effect field)
  5. Module name valid
  6. Metadata complete

Metrics

Development time:

Task Before After Savings
Files to edit 4 1 -75%
Type construction 35 LOC 10 LOC -71%
Total time 7.5h 2.5h -67%
Test setup ~50 LOC ~15 LOC -70%

Resources

Detailed Examples

For type patterns:

For testing patterns:

For comprehensive guide:

  • M-DX1-FINAL-SUMMARY.md - Complete M-DX1 summary
  • design_docs/planned/easier-ailang-dev.md - Design rationale
  • CHANGELOG.md (v0.3.10+) - Version history

File Locations

Builtin files by module:

  • internal/builtins/string.go - String functions (9 builtins)
  • internal/builtins/math.go - Math functions (37 builtins)
  • internal/builtins/io.go - IO functions (3 builtins)
  • internal/builtins/net.go - Network functions (1 builtin)
  • internal/builtins/show.go - Show typeclass (1 builtin)
  • internal/builtins/json_decode.go - JSON decoding (1 builtin)

Test files:

  • internal/builtins/*_test.go - Builtin tests
  • internal/effects/testctx/*_test.go - Test harness tests

Common Patterns

Pattern 1: Pure String Function

RegisterEffectBuiltin(BuiltinSpec{
    Module:  "std/string",
    Name:    "_str_len",
    NumArgs: 1,
    IsPure:  true,
    Type: func() types.Type {
        T := types.NewBuilder()
        return T.Func(T.String()).Returns(T.Int())
    },
    Impl: func(ctx *effects.EffContext, args []eval.Value) (eval.Value, error) {
        s := args[0].(*eval.StringValue).Value
        return &eval.IntValue{Value: len([]rune(s))}, nil
    },
})

Pattern 2: Effect Function with HTTP

RegisterEffectBuiltin(BuiltinSpec{
    Module:  "std/net",
    Name:    "_net_httpRequest",
    NumArgs: 4,
    Effect:  "Net",
    Type:    makeHTTPRequestType,
    Impl:    effects.NetHTTPRequest,  // Uses ctx.GetHTTPClient()
})

Pattern 3: Complex Record Types

See: resources/type_builder_examples.md for full example with nested records.

Progressive Disclosure

This skill loads information progressively:

  1. Always loaded: This SKILL.md file (workflow overview)
  2. Execute as needed: Scripts in scripts/ (validation)
  3. Load on demand: Detailed type examples in resources/

Notes

  • No feature flag needed (default since v0.3.10)
  • Registry auto-wires to all subsystems
  • Test harness prevents network/FS side effects
  • Metadata enables future tooling (docs, LSP)
  • Type Builder DSL is type-safe at compile time