Menu

Tools

25 built-ins, all on device

A tool is something the model can call instead of guessing — the actual date, exact arithmetic, a real JSON parse. Every built-in below runs inside Sotto with no network access at all. 4 ship switched on; the rest are one switch away in Tools.

built-in tools
25built-in tools
on after install
4on after install
calls per reply, max
4calls per reply, max
timeout per call
20stimeout per call

Why most of them ship switched off

Every tool you enable is described to the model — its name, its purpose and every parameter — before the conversation starts. Apple’s on-device model has a fixed 4,096-token window, and measured on iOS 26.5, twenty offered tools answered and called the right one while twenty-four failed outright with a bare error before running anything. So Sotto keeps the offered list inside a quarter of that window, skips what will not fit, and leaves the choice to you one switch at a time. A smaller menu also makes a 3B model choose better.

Everyday

The four that ship switched on, plus the text counter that was switched off after the system model reached for it on prompts like “say hello in one word”.

  • Date & time

    On by default

    current_datetime

    Returns the current date, time and time zone on this device. Called only when the answer cannot be given without today's date.

    No parameters

  • Calculator

    On by default

    calculate

    Works out an arithmetic expression exactly, for example 17*23 or (4.5+2)/3. Parsed by a hand-written recursive-descent evaluator rather than NSExpression, which raises exceptions Swift cannot catch.

    expression:string
    Arithmetic using + - * / % ^ ( ) and decimal numbers
  • Unit converter

    On by default

    convert_units

    Converts a number from one unit to another, for example 5 km to miles. Never invents a conversion the user did not ask for.

    value:number
    The number to convert
    from:string
    Source unit such as km, mi, kg, lb, c, f, l, gal, mph, gb
    to:string
    Target unit
  • Search my chats

    On by defaultAsks first

    search_conversations

    Searches your earlier Sotto conversations for a phrase and returns matching snippets. Everything stays on the device — but it reads your chats, so it asks first.

    query:string
    Words to look for
  • Text statistics

    Off by default

    text_statistics

    Counts the characters, words and sentences in a passage you supplied. Ships off: the system model called it on prompts like “say hello in one word”, where a word count is noise rather than help.

    text:string
    The text to measure

Dates and time

Arithmetic over dates, time zones and the calendar itself.

  • Date difference

    Off by default

    date_difference

    Measures the gap between two dates in days, weeks, months and years.

    from:string
    Start date as YYYY-MM-DD, or today, tomorrow, yesterday
    to:string?
    End date; the current moment when left out
  • Date shift

    Off by default

    date_shift

    Gives the date a number of days, weeks, months, years, hours or minutes before or after another date.

    amount:number
    How far to move; negative goes backwards
    unit:string
    days, weeks, months, years, hours or minutes
    date:string?
    Starting date; today when left out
  • Time elsewhere

    Off by default

    time_in_zone

    Reports the current date and time in another time zone and how far ahead or behind this device it is.

    zone:string
    A city or identifier such as Tokyo or Asia/Tokyo
  • Calendar facts

    Off by default

    calendar_facts

    Reports the weekday, month length, quarter, day of the year, ISO week number and leap year for one date.

    date:string?
    The date to describe; today when left out

Text

Rewriting, extracting, sorting and comparing passages you supply.

  • Transform text

    Off by default

    transform_text

    Rewrites text in a chosen style: upper, lower, title, sentence, snake, kebab, camel, pascal, slug, trim, reverse or strip_accents.

    text:string
    The text to rewrite
    style:string
    One of the styles listed in the description
  • Find and replace

    Off by default

    replace_text

    Replaces every occurrence of one exact phrase with another and says how many changed. Matches literally — a model cannot supply a regular expression that backtracks catastrophically.

    text:string
    The text to change
    find:string
    The exact phrase to look for
    replace:string?
    What to put in its place; empty deletes it
    match_case:boolean?
    Match capitalisation exactly; true when left out
  • Extract from text

    Off by default

    extract_matches

    Pulls every email, url, number, hashtag, mention, ip_address, date or phone number out of text. Eight fixed, audited patterns — never one the model wrote.

    text:string
    The text to search
    kind:string
    email, url, number, hashtag, mention, ip_address, date or phone
    limit:number?
    How many to list, 1 to 100; 25 when left out
  • Sort lines

    Off by default

    sort_lines

    Sorts the lines of a list ascending, descending, longest, shortest or reversed, and can drop repeats.

    text:string
    The lines to sort, one per line
    order:string?
    ascending, descending, longest, shortest or reverse
    unique:boolean?
    Remove repeated lines
  • Word frequency

    Off by default

    word_frequency

    Counts which words appear most often in a piece of text.

    text:string
    The text to count
    limit:number?
    How many words to list, 1 to 50; 10 when left out
    ignore_common:boolean?
    Skip words like the and of; true when left out
  • Compare texts

    Off by default

    compare_texts

    Compares two texts line by line and lists the lines that differ.

    first:string
    The original text
    second:string
    The text to compare against it

Data

JSON, CSV, descriptive statistics, percentages and number bases.

  • Format JSON

    Off by default

    format_json

    Checks that JSON is valid and rewrites it pretty-printed or minified, naming the fault when it is not.

    json:string
    The JSON text
    style:string?
    pretty or minified; pretty when left out
  • Read from JSON

    Off by default

    query_json

    Reads one value out of a JSON document by dot path, such as user.address.city or items.0.name.

    json:string
    The JSON text
    path:string
    Dot path to the value; empty returns the whole document
  • Summarise CSV

    Off by default

    summarize_csv

    Reports the rows, columns and per-column figures of CSV text.

    csv:string
    The CSV text
    delimiter:string?
    Single character between fields; a comma when left out
    has_header:boolean?
    First row holds column names; true when left out
  • Describe numbers

    Off by default

    describe_numbers

    Gives the count, sum, mean, median, minimum, maximum, range and standard deviation of a list of numbers.

    numbers:string
    The numbers, separated by commas or spaces
  • Percentages

    Off by default

    percentage

    Works out percentages: percent_of, what_percent, change between two values, or increase and decrease by a percent.

    mode:string
    percent_of, what_percent, change, increase or decrease
    value:number
    The first number
    other:number
    The second number, or the percentage for increase and decrease
  • Number bases

    Off by default

    convert_base

    Converts a whole number between bases 2 to 36, such as decimal to binary or hexadecimal.

    value:string
    The number, written in from_base
    from_base:number?
    Base it is written in, 2 to 36; 10 when left out
    to_base:number?
    Base to convert to, 2 to 36; 2 when left out

Encoding and estimation

Reversible encodings, digests, random numbers and a token-budget estimate.

  • Encode or decode

    Off by default

    encode_text

    Encodes or decodes text as base64, hex or url percent-encoding. These encodings are reversible by anyone and are not security.

    text:string
    The text to convert
    format:string
    base64, hex or url
    direction:string?
    encode or decode; encode when left out
  • Hash text

    Off by default

    hash_text

    Computes the SHA-256, SHA-384 or SHA-512 digest of text. Not for encrypting anything or storing a password.

    text:string
    The text to hash
    algorithm:string?
    sha256, sha384 or sha512; sha256 when left out
  • Random numbers

    Off by default

    random_number

    Returns up to twenty random whole numbers in a range, for dice, picks and draws. Never called to invent a figure for an answer.

    minimum:number?
    Lowest possible number; 1 when left out
    maximum:number?
    Highest possible number; 100 when left out
    count:number?
    How many numbers, 1 to 20; 1 when left out
  • Estimate tokens

    Off by default

    estimate_tokens

    Estimates how many tokens a piece of text costs a model, alongside its characters and words.

    text:string
    The text to measure

Your own tools

Three kinds you can add

These reach outside the app, so each ships disabled and defaults to asking before it runs.

  • Google search

    Searches the web through Google's Programmable Search and returns titles, snippets and links.

    Needs your own API key and search-engine id, and ships disabled. The key is stored in the system keychain rather than Sotto's database, so it never appears in an export or a log. Only the words the model searches for are sent to Google.

    iPhone, iPad and Mac

  • HTTPS request

    Calls a URL you write, with {argument} placeholders, and returns the body or a value from it.

    `https` only. Argument values are percent-encoded with &=+?#/ removed, so a model cannot append parameters or change the path.

    iPhone, iPad and Mac

  • Shell command

    Not in store builds

    Runs a command with /bin/zsh as you.

    macOS only, and compiled out of App Store builds entirely under guideline 2.5.2 — the executor refuses a shell tool left in the database by an earlier build. Arguments are single-quoted before insertion; 20 second limit.

    Mac, outside the App Store only

The tool ships switched off because it needs two things of your own. Google’s free tier allows 100 searches a day.

  1. 1Create a Programmable Search Engine at programmablesearchengine.google.com, set to search the whole web, and copy its search engine id (cx).
  2. 2Create an API key in the Google Cloud console with the Custom Search API enabled.
  3. 3Paste both into Tools › Google search, press Run once to check them, then switch the tool on.

The key is stored in your device keychain rather than Sotto’s database, so it never appears in an export or a log, and it is removed by Erase all data. Only the words the model searches for are sent to Google — never your conversation.

How a call is kept in bounds

  • Approval. Ask every time shows a card with the exact URL or command before anything runs; run automatically skips it. A new tool defaults to asking.
  • Injection. HTTPS argument values are percent-encoded with &=+?#/ removed, so a model cannot add parameters or change the path. Shell arguments are single-quoted with embedded quotes escaped.
  • Runaway loops. 4 calls per reply, 20 seconds each, results truncated at 4,000 characters.
  • No model-supplied patterns. Find-and-replace matches literally and extraction offers eight fixed, audited patterns rather than accepting a regular expression — a pattern that backtracks catastrophically would hang a reply with nothing able to stop it.
  • Personas. A persona can expose all tools, a chosen few, or none. A local-only persona never sees a tool that uses the network. One switch in Tools turns the whole feature off.