<!--
{
  "availability" : [

  ],
  "documentType" : "symbol",
  "framework" : "Tor",
  "identifier" : "/documentation/Tor/TorClient",
  "metadataVersion" : "0.1.0",
  "role" : "Class",
  "symbol" : {
    "kind" : "Class",
    "modules" : [
      "Tor"
    ],
    "preciseIdentifier" : "s:3Tor0A6ClientC"
  },
  "title" : "TorClient"
}
-->

# TorClient

Actor-isolated driver for a single embedded Tor instance.

```
actor TorClient
```

## Overview

`TorClient` is swift-tor’s primary entry point: one actor per Tor
instance, strict Swift-concurrency isolation of all mutable state,
and a high-level API that hides the dedicated `tor_run_main()`
background thread, the embedded pre-authenticated control socket,
and the `AsyncStream` fan-out of lifecycle events.

### Basic usage

```swift
let client = TorClient(configuration: .ephemeral())
try await client.start()
try await client.waitUntilBootstrapped()
print("SOCKS reachable at \(await client.socksEndpoint!)")
let control = try await client.control()
let service = try await control.addOnion(
    key: .newV3(discardPrivateKey: true),
    ports: [.toLocalPort(80, localPort: 8080)]
)
await client.stop()
```

### Thread model

Tor’s C entry point `tor_run_main()` is a blocking, single-threaded
event loop that runs for the lifetime of the Tor instance. `TorClient`
pins that loop to a dedicated `Thread` so the Swift concurrency
runtime stays free for application work; actor isolation on every
mutable property ([`state`](/documentation/Tor/TorClient/state), [`socksEndpoint`](/documentation/Tor/TorClient/socksEndpoint), the control client,
the event-continuation map) serialises callers without blocking the
Tor thread. Cross-thread bootstrapping happens through a
`CheckedContinuation` in [`start()`](/documentation/Tor/TorClient/start()).

> Note: Conformance is `Sendable` via actor isolation; no
> `@unchecked` escape hatches. Pairs with ``doc://Tor/documentation/Tor/TorSession`` for
> dependency injection (see ``doc://Tor/documentation/Tor/TorSession`` for test-double guidance).

> Important: A single `TorClient` owns its `configuration.dataDirectory`
> for the session. Constructing two clients pointed at the same data
> directory will fail the second one with ``doc://Tor/documentation/Tor/TorError/startFailed(_:)``
> due to Tor’s lockfile.

## Topics

### Creating

[`init(configuration:)`](/documentation/Tor/TorClient/init(configuration:))

Create a client bound to a specific [`TorConfiguration`](/documentation/Tor/TorConfiguration).

[`init()`](/documentation/Tor/TorClient/init())

Convenience initialiser using [`makeDefault()`](/documentation/Tor/TorConfiguration/makeDefault()).

### Lifecycle

[`start()`](/documentation/Tor/TorClient/start())

Start the embedded Tor process.

[`stop()`](/documentation/Tor/TorClient/stop())

Stop the Tor instance and release all associated resources.

[`waitUntilBootstrapped(timeout:)`](/documentation/Tor/TorClient/waitUntilBootstrapped(timeout:))

Block until Tor reports 100% bootstrap, or fail after `timeout`.

### Observing

[`state`](/documentation/Tor/TorClient/state)

Current lifecycle state, isolated to the actor.

[`socksEndpoint`](/documentation/Tor/TorClient/socksEndpoint)

Tor’s local SOCKS5 proxy endpoint once start succeeds, else `nil`.

[`events`](/documentation/Tor/TorClient/events)

Fresh fan-out `AsyncStream` of [`TorEvent`](/documentation/Tor/TorEvent) values.

### Control access

[`control()`](/documentation/Tor/TorClient/control())

Return the [`TorControlClient`](/documentation/Tor/TorControlClient) bound to this Tor instance.

[`configuration`](/documentation/Tor/TorClient/configuration)

The immutable [`TorConfiguration`](/documentation/Tor/TorConfiguration) snapshot used to start Tor.

