Platform
Provides access to Effect's platform-agnostic I/O services including HTTP clients and file systems.
Install
mkdir -p .claude/skills/platform && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/14403" && unzip -o skill.zip -d .claude/skills/platform && rm skill.zipInstalls to .claude/skills/platform
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
This skill should be used when the user asks about "@effect/platform", "Effect HTTP client", "Effect HTTP server", "FileSystem", "KeyValueStore", "Terminal", "platform services", "HttpClient", "HttpServer", "Effect file operations", "Effect networking", or needs to understand Effect's platform-agnostic I/O capabilities.Key capabilities
- →Make HTTP GET, POST, and other requests
- →Configure HTTP requests with headers, body, and timeouts
- →Handle HTTP responses by parsing JSON or text
- →Build HTTP servers with routing and request body handling
- →Perform file system operations like reading, writing, and directory management
- →Interact with the terminal for input and output
How it works
The `@effect/platform` provides cross-platform abstractions for HTTP clients, HTTP servers, file system operations, and terminal interactions, allowing for consistent I/O across different runtime environments.
Inputs & outputs
When to use Platform
- →Build cross-platform HTTP clients
- →Implement persistent storage
- →Handle file operations in Effect
About this skill
Effect Platform
Overview
@effect/platform provides cross-platform abstractions for:
- HTTP Client - Make HTTP requests
- HTTP Server - Build HTTP servers
- FileSystem - File operations
- KeyValueStore - Persistent storage
- Terminal - CLI interactions
- Worker - Background workers
HTTP Client
Installation
npm install @effect/platform
# For Node.js:
npm install @effect/platform-node
# For Bun:
npm install @effect/platform-bun
Basic Requests
import { HttpClient } from "@effect/platform"
import { NodeHttpClient } from "@effect/platform-node"
import { Effect } from "effect"
const program = Effect.gen(function* () {
const client = yield* HttpClient.HttpClient
// GET request
const response = yield* client.get("https://api.example.com/users")
const data = yield* response.json
return data
}).pipe(
Effect.provide(NodeHttpClient.layer)
)
Request Configuration
const program = Effect.gen(function* () {
const client = yield* HttpClient.HttpClient
// POST with body
const response = yield* client.post("https://api.example.com/users", {
body: HttpClientRequest.jsonBody({ name: "Alice", email: "[email protected]" })
})
// With headers
const response = yield* client.get("https://api.example.com/protected", {
headers: { Authorization: "Bearer token123" }
})
// With timeout
const response = yield* client.get("https://api.example.com/slow").pipe(
Effect.timeout("5 seconds")
)
})
Response Handling
const program = Effect.gen(function* () {
const client = yield* HttpClient.HttpClient
const response = yield* client.get("https://api.example.com/data")
// Parse as JSON
const json = yield* response.json
// Parse as text
const text = yield* response.text
// Get status
const status = response.status
// Get headers
const contentType = response.headers["content-type"]
})
Schema Validation
import { HttpClient, HttpClientResponse } from "@effect/platform"
import { Schema } from "effect"
const User = Schema.Struct({
id: Schema.Number,
name: Schema.String,
email: Schema.String
})
const program = Effect.gen(function* () {
const client = yield* HttpClient.HttpClient
const response = yield* client.get("https://api.example.com/users/1")
// Validate response with schema
const user = yield* HttpClientResponse.schemaBodyJson(User)(response)
return user
})
HTTP Server
Basic Server
import { HttpServer, HttpServerResponse } from "@effect/platform"
import { NodeHttpServer } from "@effect/platform-node"
import { Effect, Layer } from "effect"
import { createServer } from "node:http"
const app = HttpServer.router.empty.pipe(
HttpServer.router.get("/", HttpServerResponse.text("Hello, World!")),
HttpServer.router.get("/users", HttpServerResponse.json([
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" }
]))
)
const ServerLive = NodeHttpServer.layer(createServer, { port: 3000 })
const program = Effect.gen(function* () {
yield* Effect.log("Server starting on port 3000")
yield* Effect.never // Keep running
}).pipe(
Effect.provide(HttpServer.router.Live(app)),
Effect.provide(ServerLive)
)
Route Parameters
const app = HttpServer.router.empty.pipe(
HttpServer.router.get(
"/users/:id",
Effect.gen(function* () {
const params = yield* HttpServer.router.params
const id = params.id
return HttpServerResponse.json({ id, name: "User " + id })
})
)
)
Request Body
import { HttpServerRequest } from "@effect/platform"
const app = HttpServer.router.empty.pipe(
HttpServer.router.post(
"/users",
Effect.gen(function* () {
const request = yield* HttpServerRequest.HttpServerRequest
const body = yield* request.json
// Or with schema validation
const validated = yield* HttpServerRequest.schemaBodyJson(CreateUser)(request)
return HttpServerResponse.json({ created: true, user: validated })
})
)
)
FileSystem
Reading Files
import { FileSystem } from "@effect/platform"
import { NodeFileSystem } from "@effect/platform-node"
const program = Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem
const content = yield* fs.readFileString("./config.json")
const bytes = yield* fs.readFile("./image.png")
const exists = yield* fs.exists("./file.txt")
}).pipe(
Effect.provide(NodeFileSystem.layer)
)
Writing Files
const program = Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem
yield* fs.writeFileString("./output.txt", "Hello, World!")
yield* fs.writeFile("./data.bin", new Uint8Array([1, 2, 3]))
yield* fs.appendFileString("./log.txt", "New log entry\n")
})
Directory Operations
const program = Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem
yield* fs.makeDirectory("./new-dir", { recursive: true })
const files = yield* fs.readDirectory("./src")
yield* fs.remove("./temp", { recursive: true })
yield* fs.copy("./source.txt", "./dest.txt")
yield* fs.rename("./old.txt", "./new.txt")
})
File Info
const program = Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem
const stat = yield* fs.stat("./file.txt")
console.log({
size: stat.size,
isFile: stat.type === "File",
isDirectory: stat.type === "Directory",
modified: stat.mtime
})
})
KeyValueStore
Persistent key-value storage:
import { KeyValueStore } from "@effect/platform"
import { NodeKeyValueStore } from "@effect/platform-node"
const program = Effect.gen(function* () {
const store = yield* KeyValueStore.KeyValueStore
yield* store.set("user:1", JSON.stringify({ name: "Alice" }))
const value = yield* store.get("user:1")
yield* store.remove("user:1")
const exists = yield* store.has("user:1")
}).pipe(
Effect.provide(NodeKeyValueStore.layerFileSystem("./data"))
)
Terminal
CLI interactions:
import { Terminal } from "@effect/platform"
import { NodeTerminal } from "@effect/platform-node"
const program = Effect.gen(function* () {
const terminal = yield* Terminal.Terminal
const name = yield* terminal.readLine
yield* terminal.display(`Hello, ${name}!`)
}).pipe(
Effect.provide(NodeTerminal.layer)
)
Complete Example: REST API
import { HttpServer, HttpServerResponse, HttpServerRequest } from "@effect/platform"
import { NodeHttpServer } from "@effect/platform-node"
import { Effect, Layer, Schema } from "effect"
import { createServer } from "node:http"
// Schemas
const CreateUser = Schema.Struct({
name: Schema.String,
email: Schema.String
})
const User = Schema.Struct({
id: Schema.Number,
name: Schema.String,
email: Schema.String
})
// In-memory store
let users: Schema.Schema.Type<typeof User>[] = []
let nextId = 1
// Routes
const app = HttpServer.router.empty.pipe(
HttpServer.router.get("/users", HttpServerResponse.json(users)),
HttpServer.router.post("/users", Effect.gen(function* () {
const body = yield* HttpServerRequest.schemaBodyJson(CreateUser)
const user = { id: nextId++, ...body }
users.push(user)
return HttpServerResponse.json(user, { status: 201 })
})),
HttpServer.router.get("/users/:id", Effect.gen(function* () {
const { id } = yield* HttpServer.router.params
const user = users.find(u => u.id === parseInt(id))
return user
? HttpServerResponse.json(user)
: HttpServerResponse.json({ error: "Not found" }, { status: 404 })
}))
)
// Server
const ServerLive = NodeHttpServer.layer(createServer, { port: 3000 })
const main = HttpServer.serve(app).pipe(
Effect.provide(ServerLive),
Effect.catchAllCause(Effect.logError)
)
Effect.runPromise(main)
Best Practices
- Use Schema validation - Validate all external data
- Provide platform layers - NodeHttpClient.layer, etc.
- Handle errors - Network failures, file not found, etc.
- Use Effect.scoped for resources - Files, connections
- Configure timeouts - Prevent hanging requests
Additional Resources
For comprehensive platform documentation, consult ${CLAUDE_PLUGIN_ROOT}/references/llms-full.txt.
Search for these sections:
- "HTTP Client" for making requests
- "HTTP Server" for building servers
- "FileSystem" for file operations
- "KeyValueStore" for persistent storage
- "Terminal" for CLI interactions
When not to use it
- →When the project does not use Effect for application development
- →When platform-agnostic I/O capabilities are not required
- →When a different framework or library is preferred for HTTP, file system, or terminal interactions
Limitations
- →Requires providing specific platform layers (e.g., `NodeHttpClient.layer`)
- →Schema validation must be explicitly applied for external data
- →Error handling and resource management (e.g., `Effect.scoped`) are best practices to implement
How it compares
This skill offers a unified, platform-agnostic API for common I/O operations within the Effect ecosystem, providing a consistent programming model across various runtimes unlike using separate, platform-specific libraries.
Compared to similar skills
Platform side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| Platform (this skill) | 0 | 2mo | Review | Intermediate |
| telegram-mini-app | 62 | 6mo | Review | Advanced |
| stripe-integration | 48 | 2mo | No flags | Advanced |
| nodejs-backend-patterns | 12 | 2mo | No flags | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by majiayu000
View all by majiayu000 →You might also like
telegram-mini-app
davila7
Expert in building Telegram Mini Apps (TWA) - web apps that run inside Telegram with native-like experience. Covers the TON ecosystem, Telegram Web App API, payments, user authentication, and building viral mini apps that monetize. Use when: telegram mini app, TWA, telegram web app, TON app, mini app.
stripe-integration
wshobson
Implement Stripe payment processing for robust, PCI-compliant payment flows including checkout, subscriptions, and webhooks. Use when integrating Stripe payments, building subscription systems, or implementing secure checkout flows.
nodejs-backend-patterns
wshobson
Build production-ready Node.js backend services with Express/Fastify, implementing middleware patterns, error handling, authentication, database integration, and API design best practices. Use when creating Node.js servers, REST APIs, GraphQL backends, or microservices architectures.
agent-dev-backend-api
ruvnet
Agent skill for dev-backend-api - invoke with $agent-dev-backend-api
shopify-apps
alinaqi
Shopify app development - Remix, Admin API, checkout extensions
ccxt-typescript
ccxt
CCXT cryptocurrency exchange library for TypeScript and JavaScript developers (Node.js and browser). Covers both REST API (standard) and WebSocket API (real-time). Helps install CCXT, connect to exchanges, fetch market data, place orders, stream live tickers/orderbooks, handle authentication, and manage errors. Use when working with crypto exchanges in TypeScript/JavaScript projects, trading bots, arbitrage systems, or portfolio management tools. Includes both REST and WebSocket examples.