Running the host
Install the company host, check its services, and find local data and logs.
The company host runs on Debian 13, Ubuntu 22.04 or 24.04, Fedora, RHEL-compatible 10 (Rocky, AlmaLinux) or Arch Linux, on arm64 or amd64, or on a Mac with Apple silicon through Homebrew. The Linux packages need glibc 2.35 or newer. The host needs an outbound internet connection and must stay awake. The installer registers native services with systemd on Linux or launchd on macOS. It needs no public address, inbound port, or Docker installation.
Install
Download the connection file from the company setup page, then run:
curl -fsSL https://intern.kim/install.sh | sh -s -- host
sudo internkim install ~/Downloads/internkim-host.jsonThe first command installs the package through apt, dnf, pacman or Homebrew. On
Linux it fetches the package for this machine from our GitHub Releases and
checks it against the release's SHA256SUMS before the package manager installs
it. On a Mac it adds our Homebrew tap, yeomyeonggeori/tap, and installs the
internkim formula, whose bottle comes from the same GitHub Release and is
checked against the checksum the formula carries. The second command configures the company, asks for the OpenRouter API key,
and registers the host services. Without a terminal it reads the key from standard input, or from a private file named with --model-key-file. They start with the computer and recover after
a service exits. Installation finishes once every service answers and the agent
holds the company's roster, so a member can write to it right away. Then open the
printed company setup address and choose Check connection.
On Linux the connection file is optional. After the first command alone, the
computer waits for a company and shows an eight-character code at
http://<computer>.local:18088/ on its own network; sudo internkim box code
prints the same code. An administrator on that network enters it on the company
setup page, checks the last four characters of the computer's key, and confirms.
The setup page then asks for the OpenRouter key. Kim mini
describes how the claim works and how Disconnect undoes it.
Updating
A host is updated by running the installer again, by asking the agent, or from Settings.
With the installer
Run the first command again. On Linux it installs the release the channel now
points at over the version you have. On macOS Homebrew upgrades the formula and
restarts the services on it, asking for your password to do so. The company and its
data stay in place. The default channel is the latest stable release. On Linux,
--channel testing follows the newest release, prereleases included, and
--version installs one release by its tag, an older one included. A release is
named MAJOR.MINOR.PATCH, such as v0.0.1. Releases made before it
carry a date, such as v2026.10.01.203142, and still install by that tag:
curl -fsSL https://intern.kim/install.sh | sh -s -- host --channel testing
curl -fsSL https://intern.kim/install.sh | sh -s -- host --version v0.0.1The installer records the channel it followed in
/var/lib/internkim/release-channel. The tap carries only the latest release,
so a Mac stays on the default channel and cannot be pinned to a version.
By asking the agent
Any member can ask which version the host runs and whether a newer stable release is out. An administrator can ask the agent to update the host, or to take it back to an earlier stable release. The agent does this only on a Linux host installed on the stable channel, and only after the administrator confirms a question that carries the release notes, what the restart costs, and when to run it: now, at 03:00 company time, or at a time the administrator named. Nothing updates on its own.
Once confirmed, the admin gateway, which runs as root, records who asked and in
which conversation, then runs the installer with --version in a systemd unit of
its own, internkim-host-update, which outlives the restart it causes. A second
update is refused while one runs. When the agent is back it answers in that
conversation with the version the host reached, or with what failed and the
version the host is on.
From Settings
Settings shows every member the installed version, the channel, and the latest stable release with its notes. On the administrator tab, an administrator updates to that release or goes back to the previous one with a button. The click is the confirmation, so no question follows; a dialog says what the restart costs first. The call goes through the public API to the same admin gateway, which checks that the caller is an administrator and refuses a Mac or a host off the stable channel as above. The page then reads the host until it answers on the new version, and the gateway keeps the result for it, so nothing is posted to a conversation. The API starts the update at once, and only the agent schedules one for later.
What the restart costs
On a connected Linux host the update rewrites the settings the first install wrote, prepares the database again, restarts the services and returns once every one of them answers and the agent holds the roster again. The agent, the relay and the messenger are away for about a minute. A message sent in that window fails and has to be sent again. A task running at the restart is interrupted and resumed once when the agent is back; one that cannot be resumed is marked failed and its requester is told. A scheduled job due during the update runs once, late.
A company on several boxes takes a release one box at a time, standby boxes first. The service box names the release in the hosted service, each standby box takes it at its next check, and the service box installs it only once every standby seen in the last ten minutes runs it. A standby box could not take over from a snapshot made by a newer release, which is why they go first. If a standby has not taken it within twenty minutes, the update stops there, names the box, and the service box stays on its release.
A failed download or checksum installs nothing, and the host stays on its
version. A release that installs but whose services do not come back is left
installed and unconfigured, and the update names the silent service and how to
read why. sudo internkim refresh runs the same steps again once that is fixed,
and --version with the earlier tag goes back.
Remove
sudo apt remove internkim # Debian, Ubuntu
sudo dnf remove internkim # Fedora, RHEL-compatible
sudo pacman -R internkim # Arch LinuxRemoving the package stops and disables the host services and deletes the
program files, the host's Python runtime and what it prepared for the skills.
The install added no package source or signing key. The company stays on the
computer: /var/lib/internkim holds its key on the hosted service and the seed
that signs messages as each person, and /var/lib/internkim-postgres and
/var/lib/internkim-cache hold the host's database and cache. Installing the
package again brings the same company back. On Debian and Ubuntu,
sudo apt purge internkim also deletes the settings in /etc/internkim.
Neither key can be issued again, so deleting the company is left to you. The last directory holds its backups:
sudo rm -rf /var/lib/internkim /var/lib/internkim-postgres /var/lib/internkim-cache /var/lib/internkim-backupsCheck services
On Linux, systemd shows the host service state and logs:
systemctl list-units 'internkim*' 'blueclaw*' 'buzz*'
systemctl status internkim-relay
journalctl -u internkim-relay -n 50 --no-pagerThe package creates an internkim-admin group whose members can start, stop and
restart these services without sudo. The group opens nothing else on the
computer. sudo usermod -aG internkim-admin <account> adds an account to it.
On macOS, run launchctl print system/kim.intern.<service> to inspect a
service. Its logs are under /var/log/internkim/.
Settings
The installer writes company connection details and generated credentials to
the protected host data directory. Most companies do not need to edit these
files. Optional operator settings go in
/etc/internkim/company-host.env. The generated host settings
reference
lists the supported variables and their defaults. Keep API keys and connection
files out of the settings file.
Local data
The computer holds the agent's conversation history, task history, memory, workspace files, and messages waiting for delivery. These are separate from company records in the hosted service, which What lives where describes. A backup of the host holds everything on this computer that the hosted service does not.
Back up and restore
On Linux, one command writes the whole host to one archive and another brings it back:
sudo internkim backup
sudo internkim restore /var/lib/internkim-backups/internkim-backup-20261001T031500Z.tarThe services keep running while a backup is taken. Each database is dumped with
pg_dump, which reads it as of one moment, and every SQLite database among the
files is copied through SQLite's own snapshot. The archive holds:
| The agent's database | conversations, task history and the ledger |
| The messenger's database | every channel and message |
/var/lib/internkim | the company's keys, the seed that signs messages as each person, the messenger's attachments |
/workspace | every person's and circle's files and memory, with their owners and modes |
/var/lib/internkim-relay | messages and approval questions still waiting for the agent |
/root/.internkim | the admin gateway's own databases and settings |
/etc/internkim | the operator's settings |
It leaves out what the host rebuilds: the cache, which lives in memory, the
dependency caches under /workspace/shared/cache, each person's tmp, the
Python runtime, the browser's profiles and the logs.
The daily backup
The package runs internkim backup --keep 7 once a day through
internkim-backup.timer. A day the computer was off is caught up when it next
starts. To keep another number of backups, set BACKUPS_KEPT in
/etc/internkim/company-host.env. To turn the daily backup off:
sudo systemctl mask --now internkim-backup.timerAn upgrade leaves a masked timer off. sudo systemctl unmask internkim-backup.timer
and then sudo systemctl enable --now internkim-backup.timer turn it back on.
A backup made by hand prunes nothing unless it is given --keep, and pruning only
ever removes archives named internkim-backup-<time>.tar.
Keep a copy elsewhere
On a box, a snapshot sealed to the company key is also kept in the hosted service every fifteen minutes, which the company's other boxes take over from. More than one box says how. On any other computer, an archive on the computer it protects does not survive that computer. It is also unencrypted: it holds the company's keys and its people's files, and the directory and every archive in it are readable by root alone. Encrypt it as it leaves the computer, to a key that does not live there. With age and a recipient whose private key the company keeps elsewhere:
sudo cat /var/lib/internkim-backups/internkim-backup-20261001T031500Z.tar \
| age -r age1… > internkim-backup-20261001T031500Z.tar.ageThe encrypted file can then go to any S3-compatible store with rclone copy or
aws s3 cp. A key kept on the host would make the backup readable by anyone who
had the host, and lost with it.
Restore onto another computer
Install the package on the new computer with the first command under
Install, skip internkim install, and run internkim restore with
the archive. The new computer takes over the old one's place on the hosted
service, so turn the old one off first.
The restore checks every part of the archive against its recorded checksum before
it changes anything. It refuses an archive made by a newer internkim, and one holding a
database dump in an archive format newer than this computer's pg_restore reads.
A dump from a newer PostgreSQL major in a format it reads is restored in one
transaction, and fails whole if the schema uses something the older server lacks.
It then stops the
services, puts the files back, recreates each person's account from the roster in
the archive, gives every file back to its owner by account name, restores both
databases and starts the services, which bring their schemas up to the installed
version. Like the install, it returns once the agent holds the roster. A file whose owner has no account on the new computer stays owned by root,
and the restore lists it.
To restore onto the computer the backup came from, add --replace. The restore
first backs up what the computer holds now, so --replace with that archive undoes
it.
On a Mac the database is Homebrew's PostgreSQL, which internkim backup and
internkim restore do not manage. They refuse there.
The archive format
This is a stable format. A tool that writes it is restored like a backup.
The archive is an uncompressed tar of five members, in any order:
| Member | Contents |
|---|---|
databases/blueclaw.dump | pg_dump --format custom of the agent's database. A restore gives objects owned by any other role to internkim |
databases/buzz.dump | the same, of the messenger's database. When it holds one community, that community is moved to the host's relay address, 127.0.0.1:3000 |
roster.json | the policy document the agent was running, whose people and circles become accounts |
files.tar | the files, each entry named <root>/<path> with its owner and group recorded by name |
manifest.json | what the archive is and what it holds |
The manifest:
| Field | |
|---|---|
format | internkim-host-backup |
formatVersion | 1. A restore refuses a version newer than it reads |
createdAt | when the backup was taken, RFC 3339 |
packageVersion | the internkim package that wrote it, empty for a build without one |
companyID | the company whose host this is |
postgresqlMajor | the PostgreSQL major the dumps were taken from |
fileRoots | the roots files.tar holds |
members | every other member, each with name, size in bytes and sha256 in hex |
A member the manifest does not list, or one whose size or checksum differs, makes
the whole archive refused. A database dump may be absent, and that database then
starts empty. roster.json may be absent, and a file whose owner has no account
then stays owned by root. files.tar must hold the state root, with
companies/<companyID>/connection.json and its secrets directory. Its entries
are directories, regular files, symbolic links and hard links, and a restore
resolves owners by name and never by number. The roots:
| Root | On this computer |
|---|---|
state | /var/lib/internkim |
relay | /var/lib/internkim-relay |
configuration | /etc/internkim |
administration | /root/.internkim |
workspace | /workspace |
The dumps are compressed by pg_dump and nothing else is. Most of what
files.tar holds, pictures and documents, is compressed already.
Answer size
The relay replies with 413 and the byte count when an answer exceeds its
transport limit. The default ceiling is 3,000,000 bytes; set
ANSWER_BYTE_CEILING to change it. A non-positive value prevents startup.
Profile-picture limits are derived from this ceiling because base64 encoding
increases their size.
Network access
The host opens outbound connections and listens only on local interfaces. The exception is a Linux host that belongs to no company yet, which serves its pairing code on port 18088 until it is claimed. To administer the computer, use a shell on the same network or a remote access method your company controls.
On Linux, installing or upgrading the package also downloads the host's one
Python runtime from github.com into /opt/internkim/python, the pinned
libraries that read attached documents, and what each bundled skill's setup
keeps beside the skill's files: Python libraries from pypi.org and
files.pythonhosted.org, and the office skill's page renderer from
registry.npmjs.org. If any of them is unreachable, the install stops and names what it could not fetch. The host needs no Python
from the distribution. The skills run on the same runtime, as python3 in each
person's commands, and install nothing the first time someone uses them.