---
id: getting-started
title: Getting started
sidebar_position: 2
description: Install a repository-built Softchat package and complete the identity, encryption, and verification workflow.
---

# Getting started

The quickest useful integration is: import account authority once, clear the
caller-owned secret buffer, validate a peer key, and execute one bounded
operation. Android uses `SoftchatAccount` so Rust also commits protocol and
delivery state; lower-level protocol packages expose the equivalent immutable
cryptographic values.

:::warning Pre-release packages
The coordinates below are canonical, but public registry publication is not a
completed release gate. Today, build and test the matching artifact from this
repository before adding it to an application.
:::

## Add the package

<LanguageTabs>
  <TabItem value="rust">

```toml
[dependencies]
softchat = { path = "../softchat-sdk/crates/softchat" }
```

The crate currently depends on reviewed, unpublished Softrelay Git revisions,
so `cargo package` is intentionally not presented as a crates.io install.

  </TabItem>
  <TabItem value="android">

```kotlin
dependencies {
    implementation("com.softcose:softchat-android:0.1.0")
}
```

Build the AAR with `bash scripts/build-android-package.sh`. It contains
`arm64-v8a` and `x86_64` native libraries and consumer R8 rules.

  </TabItem>
  <TabItem value="swift">

```swift
dependencies: [
    .package(path: "../softchat-package")
]
```

Build the staged XCFramework/SwiftPM distribution on macOS with
`bash scripts/build-swift-package.sh`; import only `SoftchatKit`.

  </TabItem>
  <TabItem value="typescript">

```sh
bash scripts/test-javascript-package.sh
npm install ./target/packages/javascript/softcose-softchat-0.1.0.tgz
```

Node supports CommonJS and ESM. Browser and Worker consumers use the explicit
browser initializer described below.

  </TabItem>
</LanguageTabs>

## Complete one trusted operation

The sample secret is deliberately omitted. Load 32 secret bytes from your
platform authority, never from source code.

<LanguageTabs>
  <TabItem value="rust">

```rust
use softchat::LocalIdentity;

let alice = LocalIdentity::from_secret_bytes(&alice_secret)?;
alice_secret.fill(0);
let bob = LocalIdentity::from_secret_bytes(&bob_secret)?;
bob_secret.fill(0);
let bob_public = bob.public_key();

let encrypted = alice.encrypt_utf8(&bob_public, "hello")?;
let plaintext = bob.decrypt_utf8(&encrypted)?;
assert_eq!(plaintext, "hello");
# Ok::<(), softchat::SoftchatError>(())
```

  </TabItem>
  <TabItem value="android">

```kotlin
val account = SoftchatAccount.open(
    secretKey = accountSecret,
    databaseDirectory = context.noBackupFilesDir,
)
val recipient = PublicKey.parse(recipientInput)
val conversation = account.conversations.getOrCreate(listOf(recipient))

account.messages.send(
    commandId = CommandId.random(),
    conversationId = conversation.id,
    content = MessageContent(text = "hello"),
)
```

`open` clears `accountSecret`. The command commits authenticated local state,
independent recipient copies, and delivery intent before either the SDK-managed
transport or a host-owned custom transport writes socket bytes. Keep the
account for the active session and close it before switch or deletion.

  </TabItem>
  <TabItem value="swift">

```swift
let alice = try SoftchatIdentity(secretKey: aliceSecret)
aliceSecret.resetBytes(in: aliceSecret.indices)
let bob = try SoftchatIdentity(secretKey: bobSecret)
bobSecret.resetBytes(in: bobSecret.indices)

let encrypted = try alice.encrypt("hello", for: bob.publicKey)
let plaintext = try bob.decrypt(encrypted)
precondition(plaintext == "hello")
```

  </TabItem>
  <TabItem value="typescript">

```ts
import { SoftchatIdentity } from "@softcose/softchat";

const alice = SoftchatIdentity.import(aliceSecret);
aliceSecret.fill(0);
const bob = SoftchatIdentity.import(bobSecret);
bobSecret.fill(0);
const encrypted = alice.encrypt(bob.publicKey, "hello");
console.assert(bob.decrypt(encrypted) === "hello");
```

For a browser or Worker:

```ts
import { initializeSoftchat } from "@softcose/softchat/browser";

const { SoftchatIdentity } = await initializeSoftchat();
```

  </TabItem>
</LanguageTabs>

## Next

Learn the [identity lifecycle](/identity/), then choose the family you need:
[Nostr and cryptography](/nostr-and-crypto/),
[private messaging](/private-messaging/),
[chat and account events](/chat-and-account/),
[Android account runtime](/android-account-runtime/),
[relay and persistence](/relay-and-persistence/),
[Noise and synchronization](/noise-and-sync/), or
[media and HTTP plans](/media-and-http/).
