# Platform

Most real programs eventually need to touch the world outside of pure
computation: read a file, resolve a path, prompt the user, or shell out to
another command. Effect models each of these capabilities as a **service** with
a typed error channel, so platform access stays referentially transparent,
testable, and decoupled from any particular runtime.

The core services live in the main `effect` package as abstract interfaces:

- [`FileSystem`](https://effect.plants.sh/platform/file-system/) — read and write files and
  directories, stream large files, and watch for changes.
- [`Path`](https://effect.plants.sh/platform/path/) — join, resolve, normalize, and parse file paths.
- [`Terminal`](https://effect.plants.sh/platform/terminal/) — read user input and display output on the
  command line.
- [`ChildProcessSpawner`](https://effect.plants.sh/platform/child-processes/) — spawn and stream child
  processes (under `effect/unstable/process`).

Because these are abstract services, your code never depends on Node, Bun, or
the browser directly — it depends only on the interface. You choose a concrete
implementation at the edge of your application by providing a **Layer**.

## Providing a platform

On Node.js, the `@effect/platform-node` package supplies every implementation.
Rather than wiring each service individually, `NodeServices.layer` bundles the
file system, path, terminal, and child-process spawner into one layer:

```ts
import { NodeRuntime, NodeServices } from "@effect/platform-node"
import { Effect, FileSystem, Path } from "effect"

const program = Effect.gen(function*() {
  // Pull the abstract services out of context — no Node import in sight.
  const fs = yield* FileSystem.FileSystem
  const path = yield* Path.Path

  const target = path.join("/tmp", "effect-platform.txt")
  yield* fs.writeFileString(target, "hello from Effect\n")

  const contents = yield* fs.readFileString(target)
  yield* Effect.log(contents.trim())
}).pipe(
  // Provide all Node platform services in one shot.
  Effect.provide(NodeServices.layer)
)

// `runMain` runs the program and reports failures with a clean exit code.
NodeRuntime.runMain(program)
```

The program above mentions Node in exactly one place — the call to
`NodeServices.layer`. Everything else is written against the abstract services,
so the same logic runs unchanged on a different platform layer or against an
in-memory test implementation.

## Typed errors

Platform operations fail in the typed error channel rather than throwing. Every
file system operation fails with a [`PlatformError`](https://effect.plants.sh/error-management/), which
wraps a `reason` that is either a `SystemError` (an OS-level failure such as a
missing file or permission denied) or a `BadArgument` (an invalid input). The
`Path` service is simpler: its only fallible methods, `fromFileUrl` and
`toFileUrl`, fail with a `BadArgument` directly. Because the failure is in the
error channel, you handle it with the usual combinators like `Effect.catchTag`:

```ts
import { Effect, FileSystem } from "effect"

const readConfig = Effect.gen(function*() {
  const fs = yield* FileSystem.FileSystem
  return yield* fs.readFileString("config.json")
}).pipe(
  // Missing-file failures surface as a typed PlatformError, not an exception.
  Effect.catchTag("PlatformError", () => Effect.succeed("{}"))
)
```

## Granular layers

`NodeServices.layer` is the convenient default, but each service also has its
own narrow layer when you only need one capability:

- `NodeFileSystem.layer` provides `FileSystem`.
- `NodePath.layer` provides `Path` (with `layerPosix` / `layerWin32` variants).
- `NodeTerminal.layer` provides `Terminal`.
- `NodeChildProcessSpawner.layer` provides `ChildProcessSpawner`.

Continue with the page for each capability:

- [Read and write files with **FileSystem**](https://effect.plants.sh/platform/file-system/)
- [Manipulate paths with **Path**](https://effect.plants.sh/platform/path/)
- [Read input and write output with **Terminal**](https://effect.plants.sh/platform/terminal/)
- [Spawn and stream **child processes**](https://effect.plants.sh/platform/child-processes/)