######### OneChat ######### OneChat is one AI agent in a single chat that never ends. A daemon owns the agent and its memory, and you talk to it from a terminal client, Telegram, and through your WhatsApp chats. It is in early development. Linux is supported. ******* Setup ******* Data directory ============== OneChat keeps all its data in one directory, with mode 0700. It uses ``ONECHAT_DIR`` when it is set, else ``$XDG_DATA_HOME/onechat``, else ``~/.local/share/onechat``. The development shell sets ``ONECHAT_DIR`` to ``.devenv/onechat`` in the checkout. Optional settings go in ``config.json`` in the data directory: .. code:: json { "endpoint": "chatgpt", "compactor": {"model": "gpt-6.1-sol", "effort": "high"} } ``endpoint`` is ``chatgpt`` (the ChatGPT subscription, the default) or ``api`` (the OpenAI API, with ``OPENAI_API_KEY`` set). ``compactor`` is the model and effort of the memory summaries. Login ===== .. code:: console onechat login Open the link on any device and enter the code. Device code login must be allowed in the ChatGPT security settings. Do not share the login with the Codex CLI: each program logs the other out. Telegram ======== #. Make a bot with BotFather and keep its token. #. Find your numeric Telegram user ID. #. Write both to ``telegram.json`` in the data directory, with mode 0600: .. code:: json {"token": "123456:ABC-token-from-BotFather", "owner": 123456789} Start the daemon and write to the bot in a private chat. It answers only you. WhatsApp ======== Link your WhatsApp account as a linked device from the terminal client or Telegram: ``/whatsapp pair PHONE`` Gives a pairing code. On the phone, open Linked devices, Link a device, Link with phone number instead, and enter the code. ``/whatsapp status`` Shows the link and the routes of chats to child agents. ``/whatsapp unlink`` Ends the link. The session file gives full access to the account. If it leaks, remove the device in Linked devices on the phone. User service ============ Run the daemon as a systemd user service. Keep the ``result-service`` link, so that Nix keeps the package: .. code:: console nix build --out-link result-service systemctl --user link --force "$PWD/result-service/share/systemd/user/onechat.service" systemctl --user edit onechat.service In the editor, set the data directory, and the tools that the agent may use in its shell: .. code:: ini [Service] Environment="ONECHAT_DIR=DATA_DIR" Environment="PATH=TOOLS_PATH" Then start it, and let it run while you are logged out: .. code:: console systemctl --user daemon-reload systemctl --user enable --now onechat.service loginctl enable-linger "$USER" After a ``git pull``, ``bin/service-update`` builds and restarts it. Never run two daemons on the same data. Backups ======= .. code:: console onechat backup BACKUP_DIR/onechat.tar.gz ONECHAT_DIR=EMPTY_DIR onechat restore BACKUP_DIR/onechat.tar.gz A backup runs while the daemon runs. Restore needs a stopped daemon and an empty directory. **An archive holds your logins, the bot token, and the WhatsApp link**, so keep it private. For a daily backup with the last 14 kept, save this script, with ``BACKUP_DIR`` replaced by a private directory outside the data directory: .. code:: sh #!/bin/sh set -eu umask 077 cd BACKUP_DIR onechat backup "onechat-$(date +%F).tar.gz" ls -1 onechat-????-??-??.tar.gz | sort -r | tail -n +15 | xargs -r rm -- and run it from a ``Type=oneshot`` user service with the same ``ONECHAT_DIR`` and an ``OnCalendar=daily`` timer. ********* Talking ********* .. code:: console onechat ``onechat`` connects to the running daemon. Each line is a message, and replies show with Markdown styles and tables. These lines are commands: ``/stop`` Interrupts the running turn. ``/stop NAME`` Stops the subagent NAME. ``/image PATH [caption]`` Sends a JPEG, PNG, or WebP image. Quote a path with spaces. ``/whatsapp ...`` The WhatsApp commands above. In Telegram, write as in the client, also with photos and image files. ``onechat help`` lists all commands. ********************* What the agent does ********************* Memory The agent remembers the whole chat as summaries that it can open again, so it never starts over. ``agent/instructions.md`` holds your lasting preferences. The agent can propose a change to it and makes the change only after you agree. Tools The agent runs shell commands as you, in its working directory, with no sandbox. Subagents For long tasks it starts subagents in the background, such as ``GreenOtter``, and gets their reports as messages. Child agents A child is a permanent agent for one area of your life, such as ``House``, with its own memory. The root creates it, talks to it, and hears from it only what needs you. Children never send WhatsApp messages; they draft replies for you to approve. WhatsApp The agent reads your chats in batches and wakes for a private message or a mention of you. It finds chats and sends messages only when you ask. It proposes to route a chat that is only about one area to the child of that area, and sets the route after you agree. Images Send a photo in Telegram, WhatsApp, or with ``/image`` to the agent. Its memory keeps what the image shows, and it can look at an older image again. Ask it to show an image or send one to a WhatsApp chat. Schedules Ask for reminders and timed tasks, such as "every weekday at 8, tell me what my groups talked about". Each run uses the quota, so runs are at least 5 minutes apart. Import Old WhatsApp chats can join the memory in date order. Stop the daemon, export the chat as a ZIP, and run the plan before the import. The import rebuilds the target's memory with model calls: .. code:: console onechat import -n [--agent NAME] CHAT.zip onechat import [--agent NAME] CHAT.zip ***** Log ***** The daemon writes short events with ``key=value`` attributes to the user journal, at three levels: info, warning for a failure that is retried or loses nothing, and error for a failure that loses data or stops work. .. code:: console journalctl --user -u onechat -f journalctl --user -u onechat -p warning ************* Development ************* Nix supplies the Go toolchain and all tools. Enter the development shell with ``direnv allow`` or ``nix develop``. Then: .. code:: console nix build ./result/bin/onechat version bin/format bin/check nix flake check ``onechat version`` prints ``yyyy-mm-dd-gitshort`` for a Nix build and ``dev`` for a direct Go build. ``bin/check`` runs the linters and a short replay of a synthetic log, and ``nix flake check`` also runs the full replay of 100,000 messages. ``onechat probe LOG COUNT`` measures the memory summaries on a log with real model calls.