From 07d8a0b5d627b144318634e4eb5d68f1dc1d8163 Mon Sep 17 00:00:00 2001 From: notabd7-deepshard Date: Wed, 11 Mar 2026 18:59:03 -0700 Subject: [PATCH] docs --- docs/Truffle.png | Bin 0 -> 8922 bytes docs/ambient-app.mdx | 165 +++++++++++++++++++++++++++ docs/building-apps.mdx | 161 ++++++++++++++++++++++++++ docs/cli.mdx | 250 +++++++++++++++++++++++++++++++++++++++++ docs/focus-app.mdx | 197 ++++++++++++++++++++++++++++++++ docs/inference.mdx | 164 +++++++++++++++++++++++++++ docs/installation.mdx | 143 +++++++++++++++++++++++ 7 files changed, 1080 insertions(+) create mode 100644 docs/Truffle.png create mode 100644 docs/ambient-app.mdx create mode 100644 docs/building-apps.mdx create mode 100644 docs/cli.mdx create mode 100644 docs/focus-app.mdx create mode 100644 docs/inference.mdx create mode 100644 docs/installation.mdx diff --git a/docs/Truffle.png b/docs/Truffle.png new file mode 100644 index 0000000000000000000000000000000000000000..979ff73ce44802282df90fee6b713db3088d3cf5 GIT binary patch literal 8922 zcmeHN`9GBH_rGV1Wvn5z*d^JMtQm@;2U%yvSkff>*vghIlPu2@g)EUmMKUuO%UBx* zc@j!!#=cd^GRUs6eD6L#e_!7};QRXgFh9(>uIpU)eXet#^FHr${bOTg#>ahv8vp>l zzph@k0{|%I&yR}(lr($hi~)e`%fBvPLf(Zi#}Cs*K5S~QrZ4UnRLIdD0)GRFP#f4) zLA-3*QOJ?|mtjt_X@7&#K-f9Koy}^y*WFc3OR1U&gl2&?y{swOkJvSq%j(f9X=>S7 zIkW_T%-s(#;G!ag2Pn+JvjaAkG$?T9G!_CJ6($3~Lpb;-9WWID?*1EbSNfn zWZuX~c@?s#fNkZbU^iwz*J@Yq#T!u3 zo~5%_XQ&BhR1G5ad0n?xCJ)b~KsI42XZlCND_p7i5r_NRlkAF#Pt)iGm(shG$@_VN zl+fr<;coD7#o|p~mLl3&acuVu+7=+b&E+ zw-{9-^hSsf3-f~go-sOU@I?_8E>x5bPI?m z6}lRu2`;KZK8jTeP|>C@O2`O@mvJ7a{1DMQt0oqLwU#uujB}Y2pgi|wTxC(r5WzXZ zVcZP|Q_+^Yr1Wy(=g-b;IQbmhaq=FE`B!N7lBlyZw$iE8T;8&H^JzFrX(*9lZW(GZ ze#K^IdFgx>bpwQhN!i3zH~&ZK|v9jm-=+0yY@+ON7qane|gB2mJ<-5IfUBuzo6 zHs2t^%`^EX9K$Q8iR>*fawvtC7x8tLRC#F0zCJ?6AdTtCV(L9eh)#A;Rz#Uus^p7! zHOv!yhwMl;w-3Z=pA%^@dKOg{uc~@ETN>N<$XA3M&oH(eigSgjc$PS^rxY?J58DNd z-uh}>fFuu}!t8GhSQAjnUz?-P4cyt$->a?CH#17x(?ebB#$i9++Nf z>)+vTM^D%zF6>nsysdvTtKe;WjrPqHM%;bQZ=-79@!-m|Pps1yUm4QA8lGPDJ532H zIw*^w`@B?K311%DJ%eoZsF}(d1RW}&0vac(Bagi;A4lJO!EeX($~rUqHO`?8{kXu_ zC|EB}bPyc$aTGj*xo+jmKM{w-Ew-K!suHRdYFw-K9qj1wzKw#47GyoT)N*(bm84c+ zlH;aqm89lOiZ=i9tqP{{*+YtGEw4*C5_)*BpMjOPtn_F&aE{V2BHr0oytFuYBNovh zMstLz7^a`}RzeSV`>qJ(3%wG0b4QM%C=)d}@{it&m#BAJD(jA6iE}DYQK^qWRM%uw zj5&fA8L=J0Ep~y|C8{iFruo;8j~N+-?2qsr|BM~8r;Lm)yke|HtxnzN7CG8UEusi- zYrCc?F?x*-mkitB5Zv5a%`lpC`AR^XfRy3h5kikmtHGUEpCsyBj5_nOzlkwzq;hPv znYG;XX>x;~h=ij9BFQPDwN>XL7Plpce1hb#GuByfbi+q~lrbt_7FCM1^gsExIDgAb zAB;}g7b1swcB6>x(;=Ei$dV0GGxr0DH!ZYq1u)W!p#>5uE|VeUXU5~~*!PaYd5KPn z0ToJH$4^GDfAS1Kt0HGSi#It(v!Wd07}*>@{B0Vgpp1WKW;6F48ETgnetrL-@Um+_ zYRNip&^#2!6Xjp*;XO(67ba^f=@cT%81DqG8KazHbDhuHvtM5J_jkoHS$;Fk*)i1y z=L0hEluNikxGx0yG(F1Yf_iA#_65~;rVv@%^OI^TlGx9IEQ6LSd6kqm5Q;tO5l}|r zkGFZ0G9kZe6g+`|qFtj97$>|aBN2(q38T_j|BC@w z%^&hE5X4OW`to=aoix;q*q@+ADQw?mSg_-Y8RvTPvox#=47KX{d2d}4QEgvYERLfX zH)y0tmak>zlynSM+~9Gb*)WiO=Cm$E!KQ7iQ?B^e=Oq=kjv`#7PbZX|;0f?}QWBmb z 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 L)#Y+yY~23=0.27.0" "cryptography>=42.0.0" + - name: Copy application files + type: files + files: + - source: ./config.py + destination: ./config.py + - source: ./client.py + destination: ./client.py + - source: ./bg_worker.py + destination: ./bg_worker.py + - source: ./kalshi_background.py + destination: ./kalshi_background.py +``` + +--- + +## Step 2: Runtime Pattern + +Kalshi background uses the app runtime background loop (coming soon but for now you can use the example apps to see how to use it for your apps!): + +```python +from app_runtime.background import BackgroundRunContext, run_background + +def kalshi_ambient(ctx: BackgroundRunContext) -> None: + ... + ctx.bg.submit_context(content=content, uris=[], priority=priority) + +if __name__ == "__main__": + run_background(kalshi_ambient) +``` + +Core idea: + +1. gather external state (APIs, events, account state) +2. create context messages with enough detail to be actionable +3. submit with priority (`LOW`, `DEFAULT`, `HIGH`) based on urgency + +--- + +## Step 3: Submit Rich Context (Not Generic Text) + +From Kalshi, stronger context items include concrete fields: + +- ticker and title +- absolute and relative price change +- before/after values +- settlement result and revenue impact +- order IDs and status change + +Example style: + +```text +Price alert: FED-RATE-SEP moved up 12c (was 41c, now 53c) +``` + +This is much better for proactivity than broad summaries without entity/time/value details. + +--- + +## Step 4: Reliability and Cleanup + +Kalshi background explicitly closes resources on shutdown (This is important and needs to be done for your apps! Your apps will fail at runtime otherwise): + +- `atexit.register(_cleanup)` in `kalshi_background.py` +- `_cleanup()` closes `KalshiBackgroundWorker` client and event loop +- worker itself exposes `close()` and wraps API failures + +Do the same in your app. Leaving connections open at shutdown is a common source of flaky reruns and container instability. + +--- + +## Step 5: Deploy and Verify + +```bash +truffile validate ./app-store/kalshi +truffile deploy --dry-run ./app-store/kalshi +truffile deploy ./app-store/kalshi +``` + +Then verify: + +- scheduled runs execute at expected interval/window (Tip: Keep interval small when testing to see results earlier, you can adjust it and redeploy later when you know it works!) +- context submissions are visible in runtime logs, right now there is not a away for you to go and watch runtime logs for your background apps, we will be adding this feature soon to the sdk. Till then please make sure you follow the example app templates! + +--- + +## When to Use Background + +Use background apps when you need: + +- periodic polling/monitoring +- context emission for proactive behavior, you would like Truffle to take an action! (Do not be restrained in thinking that a background app can only influence actions for that app only, if I get an instagram message regarding an amazon order, Truffle can use that to do an action of adding said item to my cart!) +- domain-specific event digestion over time + +If your app also needs callable tools, keep both blocks in one app (`metadata.foreground` + `metadata.background`) as shown in Kalshi. diff --git a/docs/building-apps.mdx b/docs/building-apps.mdx new file mode 100644 index 0000000..a813f53 --- /dev/null +++ b/docs/building-apps.mdx @@ -0,0 +1,161 @@ +--- +title: What are Truffle Apps? +--- + +## What Are Truffle Apps? + +Truffle apps are containerized programs that run on your Truffle and extend what the agent on your Truffle can do. + +There are three app shapes you can build today: + +| Type | When It Runs | What It Does | +|------|--------------|--------------| +| **Foreground** | On demand | Exposes MCP tools (served over `streamable-http`) the agent can call during tasks | +| **Background** | On schedule | Submits context to the proactive agent | +| **Both** | On demand + schedule | Combines MCP tools and scheduled context submission | + + + + Full example app using both foreground tools and background scheduling. + + + Background-only example that submits periodic context. + + + +--- + +## App Config Shape (Current) + +The current SDK supports app-specific foreground/background process blocks under `metadata`. +An app can have both or either! + +```yaml +metadata: + name: Kalshi + bundle_id: org.deepshard.kalshi + description: | + Have Truffle trade and monitor Kalshi prediction markets for you. + icon_file: ./icon.png + + background: + process: + cmd: ["python", "kalshi_background.py"] + working_directory: / + environment: + PYTHONUNBUFFERED: "1" + KALSHI_API_KEY: "REPLACE_WITH_KALSHI_API_KEY" + KALSHI_PRIVATE_KEY: | + REPLACE_WITH_KALSHI_PRIVATE_KEY_PEM + default_schedule: + type: interval + interval: + duration: 30m + schedule: + daily_window: "00:00-23:59" + + foreground: + process: + cmd: ["python", "kalshi_foreground.py"] + working_directory: / + environment: + PYTHONUNBUFFERED: "1" + KALSHI_API_KEY: "REPLACE_WITH_KALSHI_API_KEY" + KALSHI_PRIVATE_KEY: | + REPLACE_WITH_KALSHI_PRIVATE_KEY_PEM + +steps: + - name: Install dependencies + type: bash + run: | + apk add --no-cache gcc musl-dev libffi-dev openssl-dev + pip install --no-cache-dir "httpx>=0.27.0" "cryptography>=42.0.0" + - name: Copy application files + type: files + files: + - source: ./config.py + destination: ./config.py + - source: ./client.py + destination: ./client.py + - source: ./bg_worker.py + destination: ./bg_worker.py + - source: ./kalshi_foreground.py + destination: ./kalshi_foreground.py + - source: ./kalshi_background.py + destination: ./kalshi_background.py +``` + +--- + +## Build and Deploy Flow + +Use this flow for all app types: + +1. Validate config and source files. +2. Check deploy plan without mutating device. +3. Deploy via builder session. + +```bash +truffile validate ./my-app +truffile deploy --dry-run ./my-app +truffile deploy ./my-app +``` + +Under the hood, deploy uses a build session, uploads declared files, runs `bash` steps, and finalizes app metadata/process config. + +--- + +## Kalshi Walkthrough: + +Kalshi is the best reference because it demonstrates both paths in one app: + +- `kalshi_foreground.py` exposes MCP tools such as `get_markets`, `get_market`, `create_order`, and `get_positions`. +- `kalshi_background.py` runs on schedule and submits portfolio/market context through `ctx.bg.submit_context(...)`. + +This is the intended split: + +- **Foreground** is your callable tool surface (MCP spec). +- **Background** is your proactive context pipeline. + +The quality of your background context directly affects proactive behavior. Rich, precise submissions perform better than generic text. + +--- + +## Runtime Stability Pattern (Important) + +In Kalshi, network clients are explicitly closed on shutdown: + +- foreground: `atexit.register(_cleanup)` calls `KalshiClient.close()` +- background: `atexit.register(_cleanup)` closes the worker client and event loop + +Do this in your own apps. Closing outbound clients/sessions before process exit prevents flaky shutdown behavior and avoids container-side runtime crashes. + +--- + +## Next Steps + + + + MCP tool server patterns, examples, and deployment details. + + + Scheduling, context submission, and proactivity-oriented design. + + + +--- + +## Contribute to the Truffle App Store + +Contributors are welcome to submit apps to the Truffle App Store. + +To submit your app: + +1. Open a PR with your app under the `app-store/` folder. +2. Include a screen recording of your app in action. + +For accepted apps, the Truffle team will deploy the app to the App Store so others can use it. Your name can be credited as the app author. In some cases, changes may be required for runtime reliability. + + + Example app card in Truffle App Store with author attribution + diff --git a/docs/cli.mdx b/docs/cli.mdx new file mode 100644 index 0000000..61231f9 --- /dev/null +++ b/docs/cli.mdx @@ -0,0 +1,250 @@ +--- +title: Truffile CLI +description: "Connect to your Truffle and deploy apps using the truffile CLI" +--- + +## Overview + +The truffile CLI lets you discover, connect to, and deploy apps to your Truffle devices. + +```bash +truffile +``` + +``` +πŸ„β€πŸŸ« truffile - TruffleOS SDK + +Usage: truffile [options] + +Commands: + scan Scan network for Truffle devices + connect Connect to a Truffle device + disconnect Disconnect and clear credentials + deploy [path] Deploy an app (reads type from truffile.yaml) + validate [path] Validate app config and files + delete Delete installed apps from device + list List installed apps or devices + models List models on your Truffle + chat Chat on your Truffle (REPL) +``` + +--- + +## Connecting to Your Truffle + +### Step 1: Scan for Devices + +Find Truffle devices on your local network: + +```bash +truffile scan +``` + +``` +βœ“ Scanning for Truffle devices (5s) + +Found 6 Truffle device(s): + + 1. truffle-6070 (192.168.1.109) + 2. truffle-5970 (192.168.1.104) + 3. truffle-6272 (192.168.1.32) + 4. truffle-7280 (192.168.1.87) + 5. truffle-0148 (192.168.1.60) + 6. truffle-6239 (192.168.1.129) + +Select device to connect (1-6) or press Enter to cancel: +``` + +Select a device by entering its number. + +### Step 2: Enter Your User ID + +After selecting a device, you'll be prompted for your User ID: + +``` +βœ“ Resolving truffle-6272.local + + Make sure you have: + β€’ Onboarded with the Truffle app + β€’ Your User ID from the recovery codes + +? Enter your User ID: +``` + + +You can find your User ID in the **Settings β†’ About** section of your Truffle desktop client. + + +### Step 3: Approve the Connection + +After entering your User ID, you'll see: + +``` +βœ“ Connecting to device + +β€’ Requesting authorization... + Please approve on your Truffle device +β ‹ Waiting for approval +``` + +A dialog will appear on your Truffle client asking you to approve the connection: + + + Approve connection dialog + + +Click **Approve** to allow the connection. + +``` +βœ“ Waiting for approval + +βœ“ Connected to truffle-6272 +``` + +### Reconnecting Later + +Once you've connected to a device, you can reconnect directly without scanning: + +```bash +truffile connect truffle-6272 +``` + +Your credentials are saved locally, so you won't need to re-enter your User ID or approve again. + +--- + +## Disconnecting + +To disconnect from all devices and clear your saved credentials: + +```bash +truffile disconnect all +``` + + +This will require you to go through the full connection process again (User ID + approval) the next time you want to connect. + + +To disconnect from a specific device: + +```bash +truffile disconnect truffle-6272 +``` + +--- + +## Deploying Apps + +Once connected, you can deploy apps to your Truffle. + + +If you haven't built an app yet, check out the [Building Apps](/sdk/building-apps) guide first. + + +### Basic Deploy + +Deploy an app from the current directory: + +```bash +truffile deploy +``` + +Or specify a path to your app folder: + +```bash +truffile deploy ./my-app +``` + +truffile will: +1. Validate your `truffile.yaml` configuration +2. Check syntax for all Python files +3. Resolve app runtime shape (**foreground**, **background**, or both) +4. Upload files and run installation steps +5. Register the app with your Truffle + +### Interactive Mode + +Deploy with an interactive terminal session for debugging: + +```bash +truffile deploy -i +``` + +This uploads your files and opens a terminal inside your app's container. You can: +- Test your app manually +- Install additional dependencies +- Debug issues in real-time + + +You can even install [Claude Code](https://claude.ai/code) inside the container to help fix or extend your app! + +```bash +curl -fsSL https://claude.ai/install.sh | bash +``` + + +Type `exit` or press `Ctrl+D` to finish the deploy. + +--- + +## Listing Apps & Devices + +### List Installed Apps + +See all apps installed on your connected Truffle: + +```bash +truffile list apps +``` + +### List Connected Devices + +See all devices you have saved credentials for: + +```bash +truffile list devices +``` + +--- + +## Inference Commands + +Inference commands available in CLI: + +```bash +truffile models +truffile chat +``` + +For `truffile chat`, runtime behavior is controlled inside REPL using slash commands (`/help`, `/config`, `/models`, `/attach`, `/reasoning`, `/mcp`, etc.). +Run `truffile chat` by itself and manage behavior in-session. +See the [Inference](/sdk/inference) page for full command details. + +--- + +## Command Reference + +| Command | Description | +|---------|-------------| +| `truffile` | Show help menu | +| `truffile -h` | Show help menu | +| `truffile scan` | Scan network for Truffle devices | +| `truffile connect ` | Connect to a specific device | +| `truffile disconnect ` | Disconnect from a specific device | +| `truffile disconnect all` | Disconnect from all devices | +| `truffile deploy` | Deploy app from current directory | +| `truffile deploy ` | Deploy app from specified path | +| `truffile deploy -i` | Deploy with interactive terminal | +| `truffile validate [path]` | Validate app config and sources | +| `truffile delete` | Delete installed apps from connected device | +| `truffile list apps` | List installed apps | +| `truffile list devices` | List connected devices | +| `truffile models` | List models on connected device | +| `truffile chat` | Start chat REPL | + +--- + +## Next Steps + +- Ready to build your own apps? Check out the [Building Apps](/sdk/building-apps) guide. +- Want to use your Truffle for AI inference? See the [Inference](/sdk/inference) guide. diff --git a/docs/focus-app.mdx b/docs/focus-app.mdx new file mode 100644 index 0000000..dca878c --- /dev/null +++ b/docs/focus-app.mdx @@ -0,0 +1,197 @@ +--- +title: Build a Foreground App +description: "Give your Truffle MCP tools it can call on demand" +--- + +Foreground apps are MCP servers. They expose tools that Truffle can call during active tasks. + + +Foreground apps on Truffle must serve MCP over `streamable-http`. `stdio` transport is not supported for deployed foreground apps. + + +If you are new to MCP itself, read the protocol docs here: + +- [Model Context Protocol Documentation](https://modelcontextprotocol.io/docs) + + +Truffle foreground apps currently support the MCP tool surface (tool registration and tool invocation over streamable HTTP). Full MCP features are still work in progress + + +### Coming Soon + +- Additional MCP assets: resources, prompts, files, and skills +- Tool icons and richer tool metadata +- Read-only tool semantics +- Tool-driven user elicitation (requesting user input from a tool flow) +- Expanded authentication and session handling for stateful MCP servers + +--- + +## What We Are Building + +This walkthrough uses the Kalshi foreground service: + +- source: [`app-store/kalshi/kalshi_foreground.py`](https://github.com/deepshard/truffile/blob/main/app-store/kalshi/kalshi_foreground.py) +- config: [`app-store/kalshi/truffile.yaml`](https://github.com/deepshard/truffile/blob/main/app-store/kalshi/truffile.yaml) (`metadata.foreground.process`) +- app source repo: [`app-store/kalshi`](https://github.com/deepshard/truffile/tree/main/app-store/kalshi) + +It exposes callable tools like: + +- `get_markets` +- `get_market` +- `get_positions` +- `create_order` +- `cancel_order` +- `kalshi_health` + +These are regular Python functions decorated as MCP tools with clear descriptions and typed parameters. + +--- + +## Step 1: Foreground Config in `truffile.yaml` + +```yaml +metadata: + name: Kalshi + bundle_id: org.deepshard.kalshi + description: | + Have Truffle trade and monitor Kalshi prediction markets for you. + icon_file: ./icon.png + + foreground: + process: + cmd: + - python + - kalshi_foreground.py + working_directory: / + environment: + PYTHONUNBUFFERED: "1" + KALSHI_API_KEY: "REPLACE_WITH_KALSHI_API_KEY" + KALSHI_PRIVATE_KEY: | + REPLACE_WITH_KALSHI_PRIVATE_KEY_PEM + +steps: + - name: Install dependencies + type: bash + run: | + apk add --no-cache gcc musl-dev libffi-dev openssl-dev + pip install --no-cache-dir "httpx>=0.27.0" "cryptography>=42.0.0" + - name: Copy application files + type: files + files: + - source: ./config.py + destination: ./config.py + - source: ./client.py + destination: ./client.py + - source: ./kalshi_foreground.py + destination: ./kalshi_foreground.py +``` + +Use literal block style (`|`) for multiline secrets like PEM keys. + +--- + +## Step 2: MCP Server Bootstrap Pattern + +Kalshi foreground uses this runtime pattern: + +```python +from app_runtime.mcp import create_mcp_server, run_mcp_server + +mcp = create_mcp_server("kalshi") + +@mcp.tool("get_market", description="Get details for a specific market ticker.") +async def get_market(ticker: str) -> dict: + ... + +def main() -> None: + run_mcp_server(mcp, logger) +``` + +`create_mcp_server(...)` and `run_mcp_server(...)` are the Truffle app runtime wrappers used by foreground apps. + +--- + +## Step 3: Tool Design Guidance (from Kalshi) + +Kalshi tools follow a useful pattern worth copying: + +1. Validate inputs early (`limit`, `depth`, enum-like args). +2. Return structured success/error payloads, not plain strings. +3. Keep tool descriptions explicit so the model can route correctly. +4. Report auth/runtime issues using runtime error reporting where needed. + +Example tools in Kalshi: + +- read path: `get_markets`, `get_market`, `get_orderbook`, `get_positions` +- write path: `create_order`, `cancel_order`, `batch_cancel_orders` +- health path: `kalshi_health` + +--- + +## Step 4: Test MCP Tools in Chat Before Deploy + +You can test your MCP server with Truffle chat before shipping app changes. + +1. Start chat: + +```bash +truffile chat +``` + +2. Connect your MCP endpoint: + +- local MCP example: + - `/mcp connect http://127.0.0.1:8000/mcp` +- hosted MCP example (Exa): + - `/mcp connect https://mcp.exa.ai/mcp?exaApiKey=&tools=web_search_exa,web_search_advanced_exa,get_code_context_exa,crawling_exa,company_research_exa,people_search_exa,deep_researcher_start,deep_researcher_check` + +3. Verify tool discovery: + +- `/mcp tools` + +4. Run a real tool-routing prompt: + +- `use the company research exa tool to find me information about SpaceX` + +This is the fastest way to validate tool schemas/descriptions and model routing behavior before deploying your foreground app package. + + +Do not commit or publish real API keys in docs, screenshots, logs, or recordings. + + +--- + +## Step 5: Connection Lifecycle and Cleanup + +Kalshi foreground keeps a shared API client and closes it on shutdown: + +- `atexit.register(_cleanup)` +- `_cleanup()` calls `await _api.close()` + +This matters in production. Explicitly closing connections before process exit prevents shutdown instability and reduces the chance of container runtime errors. + +--- + +## Step 6: Deploy and Test + +```bash +truffile validate ./app-store/kalshi +truffile deploy --dry-run ./app-store/kalshi +truffile deploy ./app-store/kalshi +``` + +After deploy, run a task that requires market data or order actions and verify Truffle is invoking the foreground tools. + +--- + +## When to Use Foreground + +Use foreground apps when you need: + +- request/response tools invoked during a task +- deterministic API integrations the model can call on demand +- low-latency, operation-style behaviors (search, lookup, actions) + +## Note +- Remember tool descriptions are very important, follow good practice and add tool descriptions with explination fo each parameter and example usage, this helps your Truffle in calling tools! diff --git a/docs/inference.mdx b/docs/inference.mdx new file mode 100644 index 0000000..401d651 --- /dev/null +++ b/docs/inference.mdx @@ -0,0 +1,164 @@ +--- +title: Inference +description: "Use models and chat on your Truffle, including image attachments in chat" +--- + +Your Truffle exposes inference directly over `/if2/v1/*`. + +- `truffile models` β€” list models on your connected device +- `truffile chat` β€” interactive chat REPL (runtime config is done with `/` commands) + +--- + +## Quick Start + +### 1) List models + +```bash +truffile models +``` + +This calls the device endpoint: + +- `GET /if2/v1/models` + +--- + +### 2) Start chat REPL + +```bash +truffile chat +``` + +`truffile chat` is REPL-first. Use slash commands inside chat to configure behavior live. + +Chat requests are sent to: + +- `POST /if2/v1/chat/completions` + +--- + +## Image Input in Chat + +Use `/attach` to attach an image to the next user message. + +Local file: + +```text +truffile chat +/attach ./my-image.png +What is in this image? +``` + +Remote URL: + +```text +truffile chat +/attach https://example.com/image.jpg +Describe this scene briefly. +``` + +After the next prompt is sent, the pending attachment is cleared. + +--- + +## Chat Commands + +Use `/help` in REPL to list commands. + +### Core REPL commands + +| Command | What it does | +|---------|---------------| +| `/help` or `/` | Show available commands | +| `/history` | Show current conversation history summary | +| `/reset` | Clear current conversation state | +| `/models` | Open model picker and switch active model | +| `/attach ` | Attach image (local path or `http(s)` URL) for next message | +| `/config` | Show current chat config values | +| `/exit` or `/quit` | Exit chat | + +### Generation controls + +| Command | What it does | +|---------|---------------| +| `/reasoning on\|off` | Toggle reasoning output | +| `/stream on\|off` | Toggle streaming output | +| `/json on\|off` | Toggle JSON response mode | +| `/tools on\|off` | Toggle built-in default tools (`web_search`, `web_fetch`) | +| `/max_tokens ` | Set max output tokens | +| `/temperature ` | Set/clear temperature | +| `/top_p ` | Set/clear top-p | +| `/max_rounds ` | Set max assistant/tool loop rounds | +| `/system ` | Set system prompt | +| `/system clear` | Clear system prompt | + +### MCP in chat + +| Command | What it does | +|---------|---------------| +| `/mcp status` | Show connected MCP endpoint + tool count | +| `/mcp connect ` | Connect external MCP server | +| `/mcp tools` | List tools from connected MCP | +| `/mcp disconnect` | Disconnect MCP session | + +`/mcp connect` expects an HTTP(S) streamable MCP endpoint. + +--- + +## Direct HTTP Endpoints + +Use your device hostname/IP directly when needed. + +List models: + +```bash +curl -sS http:///if2/v1/models +``` + +Chat completion: + +```bash +curl -sS http:///if2/v1/chat/completions \ + -H "Content-Type: application/json" \ + -d '{ + "model": "", + "messages": [ + {"role": "user", "content": "Give me one sentence about Truffle."} + ] + }' +``` + +--- + +## MCP Testing Workflow (Local and Hosted) + +`truffile chat` can be used as an MCP integration test harness before app deployment. + +### Local MCP test + +1. Start your local MCP server with streamable HTTP transport. +2. In chat, connect it: + - `/mcp connect http://127.0.0.1:8000/mcp` +3. Verify discovered tools: + - `/mcp tools` +4. Ask for explicit tool use and verify calls in output. + +### Hosted MCP test (Exa example) + +Use a hosted MCP endpoint exactly the same way: + +- `/mcp connect https://mcp.exa.ai/mcp?exaApiKey=&tools=web_search_exa,web_search_advanced_exa,get_code_context_exa,crawling_exa,company_research_exa,people_search_exa,deep_researcher_start,deep_researcher_check` +- `/mcp tools` +- prompt example: `use the company research exa tool to find me information about OpenAI` + +--- + +## Command Reference + +| Command | Purpose | +|---------|---------| +| `truffile models` | List models on connected Truffle | +| `truffile chat` | Start interactive chat REPL | + +--- diff --git a/docs/installation.mdx b/docs/installation.mdx new file mode 100644 index 0000000..7dff12e --- /dev/null +++ b/docs/installation.mdx @@ -0,0 +1,143 @@ +--- +title: Installation +description: "Install the Truffile SDK to deploy apps to your Truffle" +--- + +## Prerequisites + +- Python 3.12 or higher +- TruffleΒΉ +- The Symphony desktop client + +## Install Python + + + + ```bash + brew install python@3.12 + ``` + + Verify the installation: + ```bash + python3 --version + ``` + + + Download and install Python from [python.org](https://www.python.org/downloads/) or use Chocolatey: + + ```powershell + choco install python --version=3.12.0 + ``` + + Verify the installation: + ```powershell + python --version + ``` + + + ```bash + sudo apt update + sudo apt install python3.12 python3.12-venv python3-pip + ``` + + Verify the installation: + ```bash + python3 --version + ``` + + + +## Set Up Your Environment + +Choose your preferred method for managing Python environments: + + + + Create and activate a virtual environment: + + ```bash + python3 -m venv .venv + ``` + + + + ```bash + source .venv/bin/activate + ``` + + + ```powershell + .venv\Scripts\Activate.ps1 + ``` + + + + + If you prefer [uv](https://github.com/astral-sh/uv) for faster package management: + + ```bash + # Install uv if you haven't already + curl -LsSf https://astral.sh/uv/install.sh | sh + + # Create a virtual environment + uv venv + + # Activate it + source .venv/bin/activate # macOS/Linux + # or + .venv\Scripts\Activate.ps1 # Windows + ``` + + + +## Install Truffile + +With your environment activated, install the SDK: + +```bash +pip install truffile +``` + +Verify the installation: + +```bash +truffile +``` + +You should see: + +``` +πŸ„β€πŸŸ« truffile - TruffleOS SDK + +Usage: truffile [options] + +Commands: + scan Scan network for Truffle devices + connect Connect to a Truffle device + disconnect Disconnect and clear credentials + deploy [path] Deploy an app (reads type from truffile.yaml) + validate [path] Validate app config and files + delete Delete installed apps from device + list List installed apps or devices + models List models on your Truffle + chat Chat on your Truffle (REPL by default) + +Examples: + truffile scan # find devices on network + truffile connect truffle-6272 + truffile deploy ./my-app + truffile deploy --dry-run ./my-app + truffile deploy # uses current directory + truffile validate ./my-app + truffile list apps + truffile models # show models on your Truffle + truffile chat # open interactive REPL chat +``` + + +Make sure you've already onboarded your Truffle with the desktop client and created an account before proceeding. + + +## Next Steps + +Now that you have Truffile installed, head to the [CLI guide](/sdk/cli) to connect to your Truffle device.