$_tuish

Getting Started

Get started with Tuish - better-auth for entitlements

Getting Started with Tuish

Tuish is "better-auth for entitlements" — drop-in licensing and monetization for terminal apps.

better-auth              Tuish
───────────────          ───────────────
Auth primitives      →   Entitlement primitives
Session tokens       →   License keys
Web components       →   TUI components (Ink)
Login/signup UI      →   Purchase/manage UI

In terminal environments, the license key IS the auth. We don't do authentication — we do entitlements.

Quick Start

Step 1: Install the SDK

npm install @tuish/sdk
go get github.com/tuish/sdk-go
# Add to Cargo.toml
[dependencies]
tuish = "0.1"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
pip install tuish

Step 2: Initialize and Check License

import { Tuish } from '@tuish/sdk';

const tuish = new Tuish({
  productId: 'prod_xxx',
  publicKey: 'MCowBQYDK2VwAyEA...',  // Ed25519 public key
});

const result = await tuish.checkLicense();

if (result.valid) {
  console.log('Licensed!', result.license);
  runYourApp();
} else {
  await tuish.purchaseInBrowser();
}
package main

import (
    "context"
    "fmt"
    "log"

    tuish "github.com/tuish/sdk-go"
)

func main() {
    sdk, err := tuish.New(tuish.Config{
        ProductID: "prod_xxx",
        PublicKey: "MCowBQYDK2VwAyEA...",
    })
    if err != nil {
        log.Fatal(err)
    }

    result, err := sdk.CheckLicense(context.Background())
    if err != nil {
        log.Fatal(err)
    }

    if result.Valid {
        fmt.Println("Licensed!", result.License.ID)
        // Run your app
    } else {
        session, _ := sdk.PurchaseInBrowser(context.Background(), "")
        fmt.Printf("Complete purchase at: %s\n", session.CheckoutURL)
    }
}
use tuish::Tuish;

#[tokio::main]
async fn main() -> Result<(), tuish::TuishError> {
    let tuish = Tuish::builder()
        .product_id("prod_xxx")
        .public_key("MCowBQYDK2VwAyEA...")
        .build()?;

    let result = tuish.check_license();

    if result.valid {
        println!("Licensed!");
        // Run your app
    } else {
        let session = tuish.open_checkout(None).await?;
        println!("Complete purchase at: {}", session.checkout_url);
    }

    Ok(())
}
from tuish import Tuish

client = Tuish(
    product_id="prod_xxx",
    public_key="MCowBQYDK2VwAyEA...",
)

result = client.check_license()

if result.valid:
    print("Licensed!")
    # Run your app
else:
    session = client.purchase_in_browser()
    client.wait_for_checkout_complete(session.session_id)

The SDK handles checkout, license storage, offline verification, and cache refresh.

Key Features

FeatureDescription
Drop-in componentsEmbed purchase flow and license management in your TUI
Offline-firstLicenses work without internet after activation
Cryptographic verificationEd25519 signed, tamper-proof licenses
Your Stripe accountPayments go directly to you (Standard Connect)
Zero liabilityYou handle billing in Stripe, we handle licenses

Architecture

┌─────────────────────────────────────────────────────────────┐
│                     YOUR TUI APP                             │
│  ┌────────────────────────────────────────────────────────┐ │
│  │              TUISH COMPONENTS (@tuish/ink)              │ │
│  └────────────────────────────────────────────────────────┘ │
│                              │                               │
│                    ┌─────────┴─────────┐                    │
│                    │    @tuish/sdk     │                    │
│                    └───────────────────┘                    │
└─────────────────────────────────────────────────────────────┘

                    ┌──────────┴──────────┐
                    │     Tuish API       │
                    └──────────┬──────────┘

                    ┌──────────┴──────────┐
                    │  Your Stripe Acct   │
                    └─────────────────────┘

Next Steps