Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agents/skills/git-workflow/shared/conventional-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Valid `<type>` values:

| Type | Description | SemVer impact |
|------------|-------------------------------------------------------------------|---------------|
| ---------- | ----------------------------------------------------------------- | ------------- |
| `feat` | Introduces a new feature | MINOR |
| `fix` | Patches a bug | PATCH |
| `build` | Changes to the build system or external dependencies | — |
Expand Down
2 changes: 1 addition & 1 deletion .agents/skills/git-workflow/shared/scope-detection.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Infer scope from the folder containing the majority of the changes.

| Folder | Scope |
|-------------------------------|---------------------|
| ----------------------------- | ------------------- |
| `.github/workflows` | `github` |
| `src/Core` | `core` |
| `src/Abstractions` | `abstractions` |
Expand Down
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,30 @@ See the [examples directory](./examples/) for more complete examples, including
OpenTelemetry integration. For in-memory integration tests, use
[MinimalLambda.Testing](./docs/guides/testing.md) (a `WebApplicationFactory`-style runtime shim).

## AI Agent Skill

This repository includes a `minimal-lambda` agent skill with focused guidance for building,
debugging, testing, and reviewing MinimalLambda code without loading the full repository into agent
context.

Install it with [skills.sh](https://skills.sh):

```bash
npx skills add j-d-ha/minimal-lambda --skill minimal-lambda
```

Install globally for Claude Code:

```bash
npx skills add j-d-ha/minimal-lambda --skill minimal-lambda --global --agent claude-code
```

Update later with:

```bash
npx skills update minimal-lambda
```

## Documentation

- [MinimalLambda](./src/MinimalLambda/README.md) – Core framework documentation
Expand Down
17 changes: 17 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,23 @@ await lambda.RunAsync();
Ready to dive deeper? Check out the [Getting Started Guide](getting-started/index.md) for a complete
tutorial, or explore the [Examples](examples/index.md) to see real-world applications.

## AI Agent Skill

Use the bundled `minimal-lambda` agent skill to give coding agents focused MinimalLambda guidance
for handlers, envelopes, middleware, AOT, testing, and repo workflow.

Install it with [skills.sh](https://skills.sh):

```bash
npx skills add j-d-ha/minimal-lambda --skill minimal-lambda
```

For a global Claude Code install:

```bash
npx skills add j-d-ha/minimal-lambda --skill minimal-lambda --global --agent claude-code
```

______________________________________________________________________

## Packages
Expand Down
2 changes: 2 additions & 0 deletions skills-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
"git-workflow": {
"source": "LayeredCraft/skills",
"sourceType": "github",
"skillPath": "skills/git-workflow/SKILL.md",
"computedHash": "fbd78cda46da7d8753beca0d68ce6532589daa4da0a457aa709fe1e11da468fe"
},
"zensical-site": {
"source": "LayeredCraft/skills",
"sourceType": "github",
"skillPath": "skills/zensical-site/SKILL.md",
"computedHash": "f66b47704234c8242d45a52e3d92d5307f49254e189819165ee37845da64e9c8"
}
}
Expand Down
93 changes: 93 additions & 0 deletions skills/minimal-lambda/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
---
name: minimal-lambda
description: Work effectively with MinimalLambda, the Lambda-first .NET hosting framework in this repo and in client projects. Use this skill whenever the user asks to build, debug, migrate, test, document, or review code using MinimalLambda APIs, envelopes, middleware, lifecycle hooks, source-generated handlers, AOT/trimming, OpenTelemetry, or MinimalLambda.Testing. Trigger even when the user only mentions AWS Lambda with Minimal API-style .NET patterns, MapHandler, FromEvent, LambdaApplication, or MinimalLambda package names.
---

# MinimalLambda skill

Use this skill to give agents enough MinimalLambda project context without loading entire repo/docs.

## First move

1. Identify task area:
- client project setup/package/config template → read `references/client-project-setup.md`
- app setup/handler/DI/lifecycle → read `references/core-hosting.md` and `references/best-practices.md`
- handler shape/unit-testable handlers → read `references/patterns/handler-patterns.md`
- middleware/features/context → read `references/core-hosting.md` and `references/patterns/middleware-patterns.md`
- lifecycle hooks (`OnInit`/`OnShutdown`) → read `references/core-hosting.md` and
`references/patterns/lifecycle-hook-patterns.md`
- SQS/SNS/API Gateway/Kinesis/Firehose/Kafka/CloudWatch/ALB envelopes → read `references/envelopes.md` and `references/patterns/envelope-patterns.md`
- Native AOT/trimming/serializer context → read `references/patterns/aot-and-envelopes.md`
- integration tests/client project tests → read `references/testing.md` and `references/patterns/testing-patterns.md`
- tracing/metrics/shutdown flush → read `references/opentelemetry.md`
- compile/runtime/test failure → read `references/troubleshooting.md`
- repo contribution/source generator/AOT work → read `references/repo-workflow.md`
2. Use bundled references as the primary source. They are included so the skill works in client projects and global installs without assuming the MinimalLambda repository is present.
3. Only inspect local MinimalLambda source paths after confirming the current workspace is this repository; for repo contributions, read `references/repo-workflow.md` first.
4. Keep Lambda-first constraints in mind: source generation, AOT friendliness, scoped per-invocation services, one handler per runtime execution.

## Fast mental model

MinimalLambda = ASP.NET Core Minimal API ergonomics adapted to AWS Lambda:

```csharp
var builder = LambdaApplication.CreateBuilder();
builder.Services.AddScoped<IMyService, MyService>();

await using var lambda = builder.Build();
lambda.MapHandler(([FromEvent] MyEvent evt, IMyService service, CancellationToken ct) =>
service.HandleAsync(evt, ct));

await lambda.RunAsync();
```

Core pieces:

- `LambdaApplication.CreateBuilder()` creates standard .NET host/config/DI defaults.
- `MapHandler(...)` registers one Lambda handler. Source generator intercepts it at compile time.
- `[FromEvent]` marks deserialized event payload. At most one payload parameter.
- Other handler parameters resolve from DI/context/keyed services/cancellation token.
- Middleware wraps invocation pipeline via inline `UseMiddleware(...)` or class `UseMiddleware<T>()`.
- `OnInit(...)` runs once during cold start; `OnShutdown(...)` runs during teardown.
- `MinimalLambda.Testing` runs real pipeline in memory for client project tests.
- Envelope packages provide trigger-specific typed event/body access; use matching package rather than hand-parsing AWS records.

## Portability rule

Assume this skill may run in a client project, not the MinimalLambda repository. Do not try to read MinimalLambda repo-local source, docs, test, or example paths unless the task is explicitly about changing MinimalLambda itself or the workspace clearly contains this repository. For client-project work, answer from bundled references and the user's project files.

## Common advice patterns

Read `references/best-practices.md` before giving architectural advice.

- Prefer inline `MapHandler` arrow functions, inline middleware, and inline lifecycle hooks in
`Program.cs` when they are Lambda adapter/glue code.
- Keep complex business logic out of handlers, middleware, and hooks; put it in injected services or
small domain helpers.
- Treat `ILambdaInvocationContext`, raw AWS `ILambdaContext`, features, lifecycle context, and other
Lambda context objects as edge concerns. Almost never pass them into services; extract needed
primitive/domain values at the edge. Passing Lambda context into services is usually a
layer-boundary smell.
- Allow simple inline logic in `Program.cs` when logic is tiny and Lambda remains easy to read.
- Extract middleware classes only when middleware is complex, reusable, stateful, or worth testing
separately.
- Prefer `CancellationToken` in async handlers and downstream calls.
- Prefer scoped services for per-invocation state; singleton for reusable clients/caches.
- Avoid storing scoped services in singletons.
- Prefer typed records/responses/envelopes over anonymous response contracts.
- Keep AOT/trimming safe: avoid reflection-heavy dynamic paths unless guarded and tested.
- For direct unit tests, test services/helpers; only extract a named handler when handler adapter
logic itself needs focused tests.
- For end-to-end behavior, use `LambdaApplicationFactory<TProgram>`.

## Validation checklist

Before final answer or patch:

- Does code compile with source generation? `MapHandler` signature has 0 or 1 `[FromEvent]`.
- Does runtime call only one handler mapping path?
- Are packages matched (`MinimalLambda.Testing` same version as `MinimalLambda`)?
- Are envelope package/type and AWS trigger type aligned?
- Are middleware registered before `MapHandler`?
- Are cancellation tokens propagated?
- For repo changes: run format/tests per `AGENTS.md` when practical.
72 changes: 72 additions & 0 deletions skills/minimal-lambda/evals/evals.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"skill_name": "minimal-lambda",
"evals": [
{
"id": 1,
"prompt": "I have a .NET Lambda using MinimalLambda. Create a clean Program.cs for an order processor with DI, an inline MapHandler arrow function, cancellation token propagation, and a service boundary for non-Lambda business logic. Also mention what package/usings I need.",
"expected_output": "Uses LambdaApplication.CreateBuilder, registers services before Build, maps exactly one inline handler with one [FromEvent] OrderRequest parameter, injects IOrderService and CancellationToken, delegates business logic to the service, calls RunAsync, and explains MinimalLambda package/usings.",
"files": [],
"assertions": [
{
"text": "Output uses inline MapHandler arrow function as the Lambda adapter and delegates non-trivial business logic to a service."
},
{
"text": "Handler signature has exactly one [FromEvent] payload parameter and propagates CancellationToken."
},
{ "text": "DI registration happens before builder.Build()." },
{ "text": "Output does not recommend manual JSON parsing or reflection-based dispatch." }
]
},
{
"id": 2,
"prompt": "We're building an API Gateway HTTP API v2 Lambda with MinimalLambda and Native AOT. Show the request/response envelope pattern and serializer setup for CreateOrderRequest/CreateOrderResponse.",
"expected_output": "Selects MinimalLambda.Envelopes.ApiGateway, uses ApiGatewayV2RequestEnvelope<T> and ApiGatewayV2ResponseEnvelope<T> or ApiGatewayV2Result, includes JsonSerializerContext entries for envelope and payload/response, registers AddLambdaSerializerWithContext and ConfigureEnvelopeOptions.",
"files": [],
"assertions": [
{ "text": "Output chooses API Gateway v2 envelope/result types, not v1-only types." },
{ "text": "Output registers AddLambdaSerializerWithContext<TContext>()." },
{ "text": "Output configures envelope options TypeInfoResolver for nested body content." },
{
"text": "Output includes both envelope and payload/response types in JsonSerializerContext."
}
]
},
{
"id": 3,
"prompt": "My MinimalLambda middleware isn't seeing the order request and sometimes scoped data leaks between invocations. Review likely causes and show a better inline middleware pattern, noting when to extract a class or delegate to a service.",
"expected_output": "Explains middleware order before MapHandler, uses ILambdaInvocationContext feature helpers like TryGetEvent/GetResponse, distinguishes Items vs Properties, warns against singleton/scoped leaks, shows thin inline middleware, says to extract class middleware or services only when logic is complex/reusable/stateful/test-worthy, and keeps Lambda context objects out of services.",
"files": [],
"assertions": [
{ "text": "Output says middleware should be registered before MapHandler." },
{ "text": "Output uses context.TryGetEvent<T>() or features for typed event access." },
{
"text": "Output distinguishes per-invocation Items from cross-invocation Properties/singletons."
},
{
"text": "Output warns against capturing scoped services/state in singletons."
},
{
"text": "Output prefers inline middleware for simple Lambda glue and extracts class middleware/services only for complex, reusable, stateful, or separately tested logic."
},
{
"text": "Output says inline middleware does not support direct service injection and uses context.ServiceProvider, class middleware, or factory middleware for dependencies."
},
{
"text": "Output does not pass ILambdaInvocationContext, ILambdaContext, or feature collections into application services; it extracts needed domain values at the edge."
}
]
},
{
"id": 4,
"prompt": "Add integration tests for a MinimalLambda function. I need to override IOrderService in tests, invoke a typed event, assert success, and know when not to use a shared fixture.",
"expected_output": "Uses MinimalLambda.Testing LambdaApplicationFactory<Program>, WithHostBuilder ConfigureServices override, InvokeAsync<TEvent,TResponse>, WasSuccess assertion, and warns shared factory reuses OnInit/singletons.",
"files": [],
"assertions": [
{ "text": "Output uses LambdaApplicationFactory<Program> from MinimalLambda.Testing." },
{ "text": "Output overrides services with WithHostBuilder/ConfigureServices." },
{ "text": "Output invokes typed event using InvokeAsync<TEvent,TResponse>()." },
{ "text": "Output warns shared fixtures reuse OnInit and singleton state." }
]
}
]
}
Loading
Loading