]> git.giacomolli.uk - onechat/blob - README.rst
Select notification targets by stable ID
[onechat] / README.rst
1 #########
2 OneChat
3 #########
4
5 OneChat is one AI agent in a single chat that never ends. A daemon owns
6 the agent and its memory, and you talk to it from a terminal client,
7 Telegram, and through your WhatsApp chats. It is in early development.
8 Linux is supported.
9
10 *******
11 Setup
12 *******
13
14 Data directory
15 ==============
16
17 OneChat keeps all its data in one directory, with mode 0700. It uses
18 ``ONECHAT_DIR`` when it is set, else ``$XDG_DATA_HOME/onechat``, else
19 ``~/.local/share/onechat``. The development shell sets ``ONECHAT_DIR``
20 to ``.devenv/onechat`` in the checkout.
21
22 Optional settings go in ``config.json`` in the data directory:
23
24 .. code:: json
25
26 {
27 "endpoint": "chatgpt",
28 "compactor": {"model": "gpt-6.1-sol", "effort": "high"}
29 }
30
31 ``endpoint`` is ``chatgpt`` (the ChatGPT subscription, the default) or
32 ``api`` (the OpenAI API, with ``OPENAI_API_KEY`` set). ``compactor`` is
33 the model and effort of the memory summaries.
34
35 Login
36 =====
37
38 .. code:: console
39
40 onechat login
41
42 Open the link on any device and enter the code. Device code login must
43 be allowed in the ChatGPT security settings. Do not share the login with
44 the Codex CLI: each program logs the other out.
45
46 Telegram
47 ========
48
49 #. Make a bot with BotFather and keep its token.
50 #. Find your numeric Telegram user ID.
51 #. Write both to ``telegram.json`` in the data directory, with mode
52 0600:
53
54 .. code:: json
55
56 {"token": "123456:ABC-token-from-BotFather", "owner": 123456789}
57
58 Start the daemon and write to the bot in a private chat. It answers only
59 you.
60
61 WhatsApp
62 ========
63
64 Link your WhatsApp account as a linked device from the terminal client
65 or Telegram:
66
67 ``/whatsapp pair PHONE``
68 Gives a pairing code. On the phone, open Linked devices, Link a
69 device, Link with phone number instead, and enter the code.
70
71 ``/whatsapp status``
72 Shows the link and the routes of chats to child agents.
73
74 ``/whatsapp unlink``
75 Ends the link.
76
77 The session file gives full access to the account. If it leaks, remove
78 the device in Linked devices on the phone.
79
80 External events
81 ===============
82
83 Use ``onechat notify --source CHECK --id EVENT --text TEXT`` to send
84 external data to the root at its next turn. Add ``--agent-id ID`` to
85 select a permanent child by its stable ID. Success means accepted, not
86 processed. See ``onechat notify --help`` for the local test limits.
87
88 User service
89 ============
90
91 Run the daemon as a systemd user service. Keep the ``result-service``
92 link, so that Nix keeps the package:
93
94 .. code:: console
95
96 nix build --out-link result-service
97 systemctl --user link --force "$PWD/result-service/share/systemd/user/onechat.service"
98 systemctl --user edit onechat.service
99
100 In the editor, set the data directory, and the tools that the agent may
101 use in its shell:
102
103 .. code:: ini
104
105 [Service]
106 Environment="ONECHAT_DIR=DATA_DIR"
107 Environment="PATH=TOOLS_PATH"
108
109 Then start it, and let it run while you are logged out:
110
111 .. code:: console
112
113 systemctl --user daemon-reload
114 systemctl --user enable --now onechat.service
115 loginctl enable-linger "$USER"
116
117 After a ``git pull``, ``bin/service-update`` builds and restarts it.
118 Never run two daemons on the same data.
119
120 Backups
121 =======
122
123 .. code:: console
124
125 onechat backup BACKUP_DIR/onechat.tar.gz
126 ONECHAT_DIR=EMPTY_DIR onechat restore BACKUP_DIR/onechat.tar.gz
127
128 A backup runs while the daemon runs. Restore needs a stopped daemon and
129 an empty directory. **An archive holds your logins, the bot token, and
130 the WhatsApp link**, so keep it private.
131
132 For a daily backup with the last 14 kept, save this script, with
133 ``BACKUP_DIR`` replaced by a private directory outside the data
134 directory:
135
136 .. code:: sh
137
138 #!/bin/sh
139 set -eu
140 umask 077
141 cd BACKUP_DIR
142 onechat backup "onechat-$(date +%F).tar.gz"
143 ls -1 onechat-????-??-??.tar.gz | sort -r | tail -n +15 | xargs -r rm --
144
145 and run it from a ``Type=oneshot`` user service with the same
146 ``ONECHAT_DIR`` and an ``OnCalendar=daily`` timer.
147
148 *********
149 Talking
150 *********
151
152 .. code:: console
153
154 onechat
155
156 ``onechat`` connects to the running daemon. Each line is a message, and
157 replies show with Markdown styles and tables. These lines are commands:
158
159 ``/stop``
160 Interrupts the running turn.
161
162 ``/stop NAME``
163 Stops the subagent NAME.
164
165 ``/image PATH [caption]``
166 Sends a JPEG, PNG, or WebP image. Quote a path with spaces.
167
168 ``/whatsapp ...``
169 The WhatsApp commands above.
170
171 In Telegram, write as in the client, also with photos and image files.
172 ``onechat help`` lists all commands.
173
174 *********************
175 What the agent does
176 *********************
177
178 Memory
179 The agent remembers the whole chat as summaries that it can open
180 again, so it never starts over. ``agent/instructions.md`` holds your
181 lasting preferences. The agent can propose a change to it and makes
182 the change only after you agree.
183
184 Tools
185 The agent runs shell commands as you, in its working directory, with
186 no sandbox.
187
188 Subagents
189 For long tasks it starts subagents in the background, such as
190 ``GreenOtter``, and gets their reports as messages.
191
192 Child agents
193 A child is a permanent agent for one area of your life, such as
194 ``House``, with its own memory. The root creates it, talks to it, and
195 hears from it only what needs you. Children never send WhatsApp
196 messages; they draft replies for you to approve.
197
198 WhatsApp
199 The agent reads your chats in batches and wakes for a private message
200 or a mention of you. It finds chats and sends messages only when you
201 ask. It proposes to route a chat that is only about one area to the
202 child of that area, and sets the route after you agree.
203
204 Images
205 Send a photo in Telegram, WhatsApp, or with ``/image`` to the agent.
206 Its memory keeps what the image shows, and it can look at an older
207 image again. Ask it to show an image or send one to a WhatsApp chat.
208
209 Voice notes
210 The agent hears Telegram and WhatsApp voice notes through local
211 Whisper. Nix includes the small model. Outside Nix, set
212 ``voice.model`` in ``config.json`` and install ``whisper-cli``.
213 ``voice.transcriber`` selects another executable. No audio goes to a
214 transcription service.
215
216 Schedules
217 Ask for reminders and timed tasks, such as "every weekday at 8, tell
218 me what my groups talked about". Each run uses the quota, so runs are
219 at least 5 minutes apart.
220
221 Import
222 Old WhatsApp chats can join the memory in date order. Stop the
223 daemon, export the chat as a ZIP, and run the plan before the import.
224 The import rebuilds the target's memory with model calls:
225
226 .. code:: console
227
228 onechat import -n [--agent NAME] CHAT.zip
229 onechat import [--agent NAME] CHAT.zip
230
231 *****
232 Log
233 *****
234
235 The daemon writes short events with ``key=value`` attributes to the user
236 journal, at three levels: info, warning for a failure that is retried or
237 loses nothing, and error for a failure that loses data or stops work.
238
239 .. code:: console
240
241 journalctl --user -u onechat -f
242 journalctl --user -u onechat -p warning
243
244 *************
245 Development
246 *************
247
248 Nix supplies the Go toolchain and all tools. Enter the development shell
249 with ``direnv allow`` or ``nix develop``. Then:
250
251 .. code:: console
252
253 nix build
254 ./result/bin/onechat version
255 bin/format
256 bin/check
257 nix flake check
258
259 ``onechat version`` prints ``yyyy-mm-dd-gitshort`` for a Nix build and
260 ``dev`` for a direct Go build. ``bin/check`` runs the linters and a
261 short replay of a synthetic log, and ``nix flake check`` also runs the
262 full replay of 100,000 messages. ``onechat probe LOG COUNT`` measures
263 the memory summaries on a log with real model calls.