Expand description
Texts read and sent through your phone, as this device does its part
(docs/texts.md; the rules are sioul_core::texts, the reading and the
sending Java’s: android/…/Texts.java, TextSend.java).
- On the phone, at each exchange (
light_step, under one lock for its processes): Android’s word on each text sent copied into its outcomes; each request decided (texts::verdict), claimed in the private ledger, flushed, before Java hands it to Android; a claim with no word from Android looked for among the texts Sioul sent, else said in doubt. - On the phone, never inside an exchange (
heavy_step: after the background service’s exchange, or in a thread of the window’s): the whole history read a batch at a time (BATCHtexts,MEDIA_BATCHbytes of media put as sealed blobs), every column kept, while the phone charges; then what the phone’s texts changed, when they did (import_now); the texts deleted on the phone marked so, once a day; the sizes the settings say. - On a computer: the Texts page (
view,conversation), a text written for the phone to send (send,again); the media’s blobs brought and kept sealed (fetch_media, in a thread, never inside an exchange); how far this computer’s clock may run ahead of the phone’s. - Every line, and every media file kept here, sealed at rest with a key
made from the sharing key (
sioul_sync::textseal): no sharing key here, nothing is read or written.
Structs§
- Choice 🔒
- This device’s own texts settings (
texts.tomlin the configuration, never shared): on a computer, the phone that sends; on a phone, the largest media file it brings to your computers (MB; none:MEDIA_CAP_MB). - Clock 🔒
- How far this computer’s clock may run ahead of a phone’s (
texts/clock.jsonin the state folder): for each phone, the last time its entry said, and the least gap seen in the last day. - Files 🔒
- Where the import writes: this phone’s log, its reader, the media copied from Android for a moment.
- Gap 🔒
- Kept 🔒
- The texts, the requests and their outcomes as last read for this device:
the whole history is opened once, not at each look of the page (9,800
sealed lines read twice per conversation opened froze the window for
seconds); then only the lines the phones’ logs added (
rules::Logs: the page reads itself again at each exchange that brings a text), and the requests and outcomes again when their files changed (size and time). The texts each once across phones (rules::one_each), with the country their numbers were keyed by, without the rows’ raw columns (fields,addrs), which only the fingerprints read. - Part
Result 🔒 - One result, as Java wrote it (TextSend.line): a text’s part sent or delivered; or a multimedia message’s word (“mms”): Android’s code, the row it filed, the HTTP status, the carrier’s answer (M-Send.conf, hex).
- Phone 🔒
- This phone’s Android.
- Raw 🔒
- A row as Java read it (Texts.sms, Texts.mms; android/jvm-checks/TextsCheck.java): every column.
- Read 🔒
- What a step read: its texts as they travel, the media bytes put in the sharing.
- Reader 🔒
- The reader’s state and the import’s measures, private to the phone
(
texts/reader.jsonin the state folder): the rows its log holds, those still to read, when the import began, what the phone holds and how much has gone. - Rows 🔒
- Rows of the provider’s two tables (
texts::Row), asreader.jsonkeeps them:[id, date]each, in order. - Step 🔒
- What the phone’s quick step works with: where it reads and writes (the data folder’s texts, the private texts folder, the other copies of the requests, the sharing’s memory), the sharing’s folder and key, Android (a stand-in in tests).
Enums§
- Prepared 🔒
- A multimedia message made ready on the phone, before its claim.
- Seal 🔒
- What seals the lines and the media: the sharing key’s, or the demo’s stand-in (plain; a line marked).
- Weigh 🔒
- What one multimedia message from here may weigh (decision 5).
Constants§
- ANDROID_
MAX 🔒 - Android’s own maximum when the carrier’s file says nothing (bytes): 300 kB.
- CAPS_MB 🔒
- The sizes offered for the largest media file (MB): the blobs take 64 MB at most.
- DAY_MS 🔒
- A day, in milliseconds.
- LOOKS 🔒
- The settings and your lists and address books, as the page last read them: read again when the settings’ file changed, or after a minute.
- LOOK_
AGAIN_ 🔒MS - A day’s look that could not list every row is tried again this long after.
- LOW_KB 🔒
- The smaller choice of Settings ▸ Texts (kB).
- MMS_
FROM 🔒 - A multimedia message’s address types (
addr.type): who sent it, to whom. - MMS_
NOTIFICATION 🔒 - A multimedia message still to download (
m_type: Android has only its notification). - MMS_
SHARE 🔒 - How many multimedia messages, at most, a step reads beside the texts.
- MMS_TO 🔒
- OUTGOING 🔒
- Where a multimedia message waits on the phone, in the private texts folder.
- OWN_
ADDRESS 🔒 - What Android writes for “this phone” in a message’s addresses.
- READER_
VERSION 🔒 - The reader of the archive. The first version read 30 days: its marks
would pass the history, so its reader starts again from the first row.
The second and third knew rows by their ids alone: the log tells which
rows it holds (
Reader::index), and what it lacks is read as a history. - RESULTS_
ASIDE 🔒 - Java’s results set aside at the last trim (
trim_results), read beside its file until the next.
Statics§
- ATTACHING 🔒
- One attaching at a time: a second one waits, then makes its own anew.
- ATTACH_
TURN 🔒 - Each attaching’s turn, and each letting go’s: an attaching whose turn
passed (a newer one asked, or the files let go meanwhile) makes nothing,
or deletes what it made. The window never waits on
ATTACHING. - FETCHED 🔒
- The phones’ logs as last seen by
fetch_media(each file’s size and time), and whether media were left for next time: nothing new, nothing done. - KEPT 🔒
- LIMITS_
ASKED 🔒 - When the carriers’ limits were last asked in this process (ms): once an hour at most.
- RESULTS_
TRIMMED 🔒 - When Java’s results were last trimmed in this process (ms): once a day.
- TRIMMED 🔒
- When this device last took its old requests and outcomes out (ms): once a day.
- WORKING 🔒
- The import (a phone’s window) or the media’s fetching (a computer) running in a thread of this process.
Traits§
- Android 🔒
- What the import asks Android (Java’s
Texts.call, throughsteps::java): the phone’s own provider of texts; a stand-in in tests.
Functions§
- again 🔒
- Send again: a request of its own, a new key, the same number and words; a multimedia message’s media again, sealed in the sharing already.
- ahead_
of 🔒 - How far this clock may run ahead of a phone’s (ms): the least gap of the last day, 0 unknown.
- ask_
media_ 🔒again - A medium the page shows that is not here: Sioul keeping the folder itself
asks for it again as if new, once it had stopped asking (three days in
vain,
sioul_sync::remote::sealed_step; review of 18 October 2026, L-8). - at_
start 🔒 - At the window’s start (lib.rs
run, once this process is the profile’s Sioul): what an earlier run left attached on the Texts page, one that quit or crashed with files attached, goes (the review of 18 October 2026, I-6). - attach 🔒
- The files chosen on the page (
sources, files or their addresses) made fit for one multimedia message to a conversation (attach::make; what an earlier attaching made goes first), off the window’s thread: {round (as asked: the page keeps its latest), media: [{source, kind, ct, path, url, size, said}], said: [why each other did not go], limit (its words), max (bytes)}. Nothing travels until Send. - attach_
limit 🔒 - What a multimedia message from here to a conversation may weigh (bytes)
and its pictures’ long side at most (0 none), from the phone that sends
(
weigh); else why nothing can be attached, its words’ key: no phone, a group (a later step), the phone not having said what its carrier takes (Attach is offered only once it has, decision 11), its carrier taking none. - attach_
made 🔒 - The files chosen made fit (
attach::make), on a computer. - attached_
folder 🔒 - Where the files attached on the page wait, made fit (Sioul’s cache, yours alone).
- before_
exchange 🔒 - Before an exchange: on a phone, the quick part of its step; on a
computer, how far its clock may run ahead of the phone’s. Then, in a
thread of its own that never holds the exchange: the import’s next batch
(a phone’s window; the background service runs it after its exchange) or
the media brought here (a computer); what came said to the window (
qt) as an exchange’s news are (shared_in), so that the pages showing texts read them again at once. Once a day, old requests and outcomes out (texts never). - bring_
media 🔒 - Each part of a message that travels, copied from Android into the
private folder, hashed, put in the sharing as a sealed blob (never inside
a line), the copy deleted; within
budgetbytes, the first part of a step always. Whether every part was brought (else the message waits for the next step). - call 🔒
- What the window asks (
Sioul::texts): “view” {query}, “conversation” {id}, “send” {to, body}, “send-mms” {to, words, media: [{ct, path}], phone} (a multimedia message, its media made fit already byattach: a file elsewhere is refused), “again” {key}, “parts” {body, media: [{ct, size}], id, phone} (with media, how much the message takes), “sending” and “limit” {value} (Settings ▸ Texts on a computer), “media” {hash, ct} (its address, to show or open it), “save-media” {hash, ct, path}, “close” (the page closed: the media opened for it and the files attached deleted), “unattach” (the files attached let go), “setup”, “ask” (Android’s question for the permissions), “info” (Sioul’s app info), “part” {on}, “cap” {value}; and “access…”, what Android withholds here (access::call). Its JSON, and whether what travels changed (to share now). - cap_mb 🔒
- The largest media file brought to your computers, in MB.
- changes 🔒
- Java’s word on the phone (
Texts.changes): whether its texts changed since it was last asked withclear(a text came, was sent, deleted or read: Android’s provider watched by the background service; not watched in this process, or no answer: yes, as at every step before), and whether the phone is on its charger. - choice 🔒
- choice_
path 🔒 - conversation 🔒
- One conversation (TextsPage.qml): {id, title, messages, can_write, group, attach (Attach offered: the phone said what its carrier takes), attach_said (else why not)}.
- conversation_
of 🔒 - A person’s conversation on the Texts page, from their numbers as written: the first whole one, keyed; “” while texts are not read here.
- delete 🔒
- A conversation deleted in Sioul (23 October 2026): Sioul is never the phone’s SMS app (it asks no SMS role, docs/texts.md), so Android lets it delete nothing from the phone’s provider. Its texts until now leave Sioul on every device (a sealed mark; the phone writes its log again without them, so every computer’s copy follows); the phone’s own texting app keeps them. A text that comes later starts it again.
- demo 🔒
- The demo profile (
SIOUL_DEMO=1, which tools/demo/run.sh sets in its sandbox with no network, and nothing else does): its texts are stand-ins written plain by tools/demo/make-demo.py, its phone a stand-in. - draft_
taken 🔒 - A draft an AI agent wrote, used (its words, for the box: sending stays yours) or discarded: taken out of the drafts either way. {body}, “” when gone.
- failed_
status 🔒 - The carrier’s refusal Android read for a message it filed among the
failed (box 5), its status (
resp_st, asTexts.findMmsgives it), when it read one: none when Android filed it there with no answer it could read (SendRequest.persistIfRequired). - fetch_
media 🔒 - The media the texts name and this device has not yet: brought from the
sharing’s blobs, sealed here,
MEDIA_BATCHbytes at a time (the first always); one the sync app has not brought yet waits for next time. Whether one was brought. - folding 🔒
- Whether a phone’s notification of a text (its sender’s key, its time) is a text the Texts page holds, or held before its conversation was deleted: folded into it, never a second item on the Porch. None where texts are not read here: every notification stays a line.
- forget_
hidden_ 🔒media - The media of hidden texts gone from this device’s copies, unless a text shown holds them too.
- guard 🔒
- What the tab says beside its question once the texts’ permissions were
asked and are still not all given (
Texts.state): “guarded” on Android 15 and later, where restricted settings may keep them from an app installed from a file (13 and 14 keep notification access only); “at-once” when Android answered without showing a question (“Don’t allow” chosen twice); else “”. - heavy_
step 🔒 - The part that may take a while, never inside an exchange: the import’s
next step when due (
import_now: caught up, what came; a history, all of it, on the charger), else the newest texts while a history waits for the charger (recent_now); and the day’s look for deletions. Under its own lock: one import at a time on the phone. - here_
media 🔒 - import_
now 🔒 - Whether the import reads the phone’s texts now, at
now(ms; docs/texts.md, “Reading, on the phone: paced”). A history (the first import’s, or a block of old texts put at once), all of it only while the phone charges: it may write and send hundreds of megabytes, on mobile data too. Caught up, when the phone’s texts changed since the last look, when the last step left texts that came (their media over its share), and with the day’s look for deletions all the same (a change Android did not say): most steps find nothing new, and ask Android nothing. - import_
step 🔒 - One step of the import (docs/texts.md, “Reading, on the phone: paced”).
Every row the phone holds is listed with its date (
texts-ids), and those its log lacks are the ones to read, wherever their ids are (the plain texts’ table gives a deleted newest text’s id to the next one; a provider emptied starts again at 1). Rows that appeared since the last step are read at once, on the battery too, oldest first; 500 or more at once are no texts that came but a block of old ones (SMS Backup & Restore restoring a history), read as a first import is: the newest first by date, withall(on the charger)BATCHat a time, else only those newer than the newest text read before and than a day before the history was found, so that a text that comes meanwhile reaches your computers within a minute or two. Media withinMEDIA_BATCHbytes, the first always. A step with nothing to read asks Android one listing. Whether anything was written. - importing_
in_ 🔒bulk - A bulk import going on, on the charger or waiting for it (
import_now): the sharing’s full rounds wait meanwhile (steps), so that it does not restate the records again and again (8 October 2026: a first import made six full rounds, each sent twice). - int 🔒
- kept_
words 🔒 - What this device keeps of the texts, for its part’s line in the sharing panel (“Keeps 4,830 texts and 210 MB of media here.”); “” when none.
- let_
attached_ 🔒go - The files attached let go, and any attaching under way told so: the window’s thread never waits.
- light_
step 🔒 - The quick part of the phone’s step, at every exchange: Android’s words copied, the requests decided and sent, a lost claim looked for, what the carriers let it send said (once an hour at most), what a multimedia message left behind swept. Under one lock for the phone’s processes. Whether something was written.
- limit_
lines 🔒 - What a phone’s carriers take, in words, read only: one line, or one a SIM in its order (“SIM 2: multimedia messages up to 600 kB. Pictures up to 2592 × 1944 pixels.”); none said yet.
- limits_
from 🔒 - What each SIM’s carrier lets the phone send, as Java read it (
Texts.limits). - listed 🔒
- Every row the phone holds, from a
texts-idsanswer: each id with its own date (sms_at,mms_at). None when the dates did not come with the ids: then nothing is read for this step, never every row taken as new. - look_
again 🔒 - Once a day: what the phone holds measured for the settings; the log’s
own counts taken again (
Reader::index); and each text gone from the phone marked so in the log, a line each, once (the archive keeps the text): a row the phone no longer lists, by its id and its date, so that a text deleted and the next one taking its id are told apart. The rows to read are the steps’ own (import_step). Whether a line was written. - looked 🔒
- Whether Java could look in the provider (
Texts.findMms): the permission given and the query answered. A look not made is never read as “not there”: made again at the next step. - looks 🔒
- The settings and your senders for the page’s looks (
LOOKS): each opening of a conversation read them twice, on the window’s thread. - made_in 🔒
- Whether
pathis a file infolder(the files attached, made fit), its links and..resolved: none elsewhere is sent as a medium. - mark_
read 🔒 - A conversation opened in Texts: read up to its newest text, on every device, and the phone’s notifications of it seen (gone from the Porch’s notices).
- marked 🔒
- Every device’s marks, and every text with those hidden: for the Porch’s folding (a notification of a text deleted since folds into nothing shown).
- measure_
clock 🔒 - At each exchange: the sending phone’s entry’s time, when it changed, compared with this computer’s clock; the least such gap of the last day is how far this clock may run ahead of the phone’s (transit included: an upper bound, so that a request looks older, never younger).
- media_
path 🔒 - A media file kept here, sealed:
texts/media/<hash>in the data folder. - media_
to_ 🔒send - The media of this computer’s multimedia messages that may still go (written
within their quarter of an hour), by their sealed files’ names in the
sharing and the size each was sealed at: they go up first on the urgent
lane (
remote::send_urgent), before the request that names them. - mms_
outcomes 🔒 - Each multimedia message’s outcome from its result (
texts::took, with the HTTP status Java read): sent (Android’s Ok and the carrier’s), not sent and why, in doubt when each of Android’s tries ended on the network (“network”: the carrier may have it); and the keys whose result is Android’s Ok without the carrier’s answer, for the sent box to say (Step::copy_results). Never “delivered”: no report is asked. - name_
rows 🔒 - Each outcome’s row by its name in the log (
texts::Row::name): Android says a sent message’s row by its id alone, which an older one may have held (the plain texts’ table gives a deleted newest text’s id again); the row’s date, read from Android now, tells which it is (a multimedia message’s in seconds). A row Android no longer holds is left unnamed, never named after an older message. - names 🔒
- notices 🔒
- The Porch’s notices of texts not read yet (23 October 2026): one per conversation, its sender and the newest’s first words, opening it in Texts; [] where texts are not read here.
- now_ms 🔒
- open_
media 🔒 - A media file opened for the page or saved: its plain copy in
opened_folder; none when it is not here. - opened_
folder 🔒 - Where a media file is opened for the page: Sioul’s cache (yours alone), emptied when the page closes.
- outcomes_
from 🔒 - Each text’s outcomes from its parts’ results: sent when every part was; not sent, and why, when one was not; delivered when the carrier said every part was received (never “not delivered” for a report that did not come).
- part_of 🔒
- A part as it travels: its words in the line; its content said, to be put
in the sharing (
bring_media) when it is not overcapbytes. - parts 🔒
- How many texts a draft takes: {parts, said}.
- parts_
mms 🔒 - How much a multimedia message takes, as its words are typed: {parts,
said (“One multimedia message (412 kB of 600 kB)”), over, max (bytes)},
its media counted by their lengths alone (
mms::size_with_lengths). - phone 🔒
- Whether this device reads and sends texts: a phone. SIOUL_TEXTS makes a computer’s step run too, to look at it.
- phone_
step 🔒 - The background service’s step, after its exchange: the quick part, then the import’s next batch. Whether something was written to share now.
- phones 🔒
- The phones in the sharing, the one chosen to send first, else the one that shared last.
- private 🔒
- raws 🔒
- read_
rows 🔒 - The rows
wantedread from Android in one question, taken in that order, each as it travels, its media put in the sharing withinbudget(the first medium of a step always). A multimedia message whose media do not fit stops the multimedia messages there for this step; the plain texts go on. A row gone meanwhile, or whose id another row took meanwhile, is left to the next listing. None when Android did not answer. - readable 🔒
- Whether the Texts page has something to show here: the part on, and a phone that sends.
- reason_
of 🔒 - Android’s code for a part not sent, as the words say it (SmsManager’s RESULT_ERROR_…).
- recent_
now 🔒 - Whether the newest texts are read now while a history waits for the
charger (
import_now): at a first import, at the first step of a reader of an older version (its log tells which rows it holds), then each time the phone’s texts changed, on the battery too; only the rows that came and the history’s newest (import_step), so that a text that comes during a long import reaches your computers within a minute or two. - records 🔒
- The texts, the requests and their outcomes (
KEPT): the logs read on where they grew, the texts made again only then (or for another country); the requests and outcomes read again when a file changed. The texts each once, a text found in two phones’ logs (a restore onto a new phone) shown once (rules::one_each). - request_
mms 🔒 - A multimedia message’s request, its media sealed in the sharing already.
- requests_
from 🔒 - The requests under each root (
<root>/send/<device>.jsonl), each key once, the first root’s first: the ledger then decides each once. - results_
of 🔒 - Java’s results (
TextSend.Result‘s lines): its file, and the one set aside at the last trim; only those of the outcomes’ month (rules::KEPT_DAYS), so that a result whose outcome was trimmed is never said, written and shared again (the review of 18 October 2026, I-f). - root 🔒
- row_of 🔒
- “content://sms/414” → “sms-414”, “content://mms/sent/31” → “mms-31”: the
row as the log names it, its date read after (
name_rows). - sealed 🔒
- This device’s name in the sharing, the sealer, and the sharing’s folder and key, while the part “texts” is on here (the demo: no folder).
- sealed_
here 🔒 - Whether a multimedia message’s media are all in the sharing (the folder, or the copy fetched from its server beside it), not opened.
- send 🔒
- A text written here for the phone to send: refused at once when the phone would refuse it (said why), else a request with a key of its own in this device’s file, which the sharing carries. {said, shared, key}.
- send_
mms 🔒 - A multimedia message written here for the phone to send (docs/texts.md,
“Multimedia messages sent from a computer”; the media reduced already,
each its content type and bytes): refused at once when the phone would
refuse it (said why); else each medium sealed into the sharing’s blobs
(content-addressed: one sent twice travels once) and into this
computer’s own media, so that the message shows it at once, then the
request, whose media go up before it (
media_to_send). Never a file’s own name: a medium is its content alone. {said, shared, key}. - sending 🔒
- Settings ▸ Texts, on a computer: how much a multimedia message from here may weigh, the carrier’s or less (300 kB), and what the phone said its carrier takes, read only. {limit: a setting’s row, phone: its lines}.
- sending_
phone 🔒 - sends_
texts 🔒 - Whether a phone sends texts for this computer: the part on here, and its texts read here (its log): a text that came to it is answered from it.
- sent_
row 🔒 - The row Sioul’s multimedia message was filed as in the sent box, by its
key (
tr_id), as Java found it (Texts.findMms: Sioul’s rows alone): its name in the log; none in the sent box (a failed one is out of sight). - sent_to 🔒
- The texts this computer wrote from a phone to a number (
dial) since a moment (ms), oldest first, for the Porch’s reply under a line (replies::Mine): the words and their state in the texts’ own words (“Sent at 14:03.”). - set_cap 🔒
- The largest media file brought to your computers, chosen on the phone (MB).
- set_
limit 🔒 - The most a multimedia message from here may weigh: the carrier’s (“carrier”) or 300 kB (“300”).
- setup 🔒
- The phone’s tab (TextsSetup.qml): {android, state (each permission, the SIMs), on (the part here), sharing, progress (what the phone holds and how much has gone), importing (more to go), cap (the setting row of the largest media file brought)}.
- size_
words 🔒 - “1.2 MB”.
- stamps 🔒
- Each file of the requests and the outcomes, its size and time.
- standing_
in 🔒 - Where a device stands, by the sharing’s two sets (
share::asking). - standing_
of 🔒 - Where each device that may ask this phone stands in the sharing now
(
share::asking), for the replies’ step (replies.rs). - string 🔒
- text_of 🔒
- A row Java read, as it travels: its people keyed (its conversation’s,
else its own addresses), its words, its parts said (their content left for
bring_media), every column kept as it came. - texted_
since 🔒 - The numbers this computer texted (
phones::key) whose phone took the text since a moment (ms, the phone’s clock): handed, sent or delivered then. - threads_
of 🔒 - The conversations’ people of a
texts-readanswer, by thread. - trim_
results 🔒 - Java’s results file kept to the outcomes’ month, once a day, in the phone’s step under its lock (the review of 18 October 2026, I-f). Java appends to it by its name at any moment, from either of the phone’s processes: it is never written over. It is set aside by a rename, and the lines kept are appended to the new one Java’s next line makes; the file set aside is read too until the next trim, which first brings back the line Java may have appended to it as it was renamed.
- unhex 🔒
- Hex’s bytes; none for what is not hex.
- view 🔒
- The Texts page’s list (TextsPage.qml): {can (the part on, a phone that
sends), phone: {id, name, shared, said}, conversations, said, never,
empty (the list’s words when it has no row)}; without them,
canfalse and why. Withquery, the conversations holding a text with all its words (or whose people’s names or numbers do), each with the newest such text as its last words. - weigh 🔒
- What one multimedia message from here to a conversation (
id, its number’s key) may weigh, from a phone (decision 5): as the phone last said its carriers take (texts::limits_of), for the SIM the conversation last used (weighed). - weighed 🔒
- What a message may weigh by what the phone said (
limits, none before it said): its carrier’s forsim(the conversation’s last; when it is unknown, -1, or the phone did not name it, the smallest of those that take multimedia messages), and no more than chosen here (chosen_kb, Settings ▸ Texts: 300 kB); with the carrier’s largest picture’s long side. - with_
drafts 🔒 - The conversations with the drafts an AI agent wrote for them (
textdraft, docs/mcp.md, “Texts”): how many wait in each, said under its last words; a draft to someone with no conversation yet makes one, first. - write_
flushed 🔒 - A private file written whole beside, flushed to the disk, then put in place.
- write_
log 🔒 - Texts added to this phone’s log, each line once: how many were written, or why none could be.
- write_
whole 🔒 - A private file written whole beside, then put in place.
Type Aliases§
- Vault 🔒
- The sharing’s folder and key: where the media’s blobs go and come from.