Run the official Grok Bot local-computer daemon on a Linux host without the Electron chat window, a renderer, X11, Wayland, or Xvfb.
grokbot-headless is a small, unofficial management layer. It authenticates, starts, and supervises the local-execution daemon that is already present in the official Grok Bot Linux package. It does not replace Grok Bot and does not include proprietary Grok Bot code.
Warning
This project uses an internal Grok Bot protocol. xAI does not publish this protocol as a stable public API. A Grok Bot update can require a matching controller update.
- How it works
- Requirements
- Quick start
- Execution policy
- Commands
- Compatibility checks
- Updates
- Service operation
- Files and credentials
- Security
- Custom paths
- Troubleshooting
- Development
- Uninstall
- Legal status
The official Grok Bot desktop application normally performs these tasks:
- Authenticate the user.
- Register the local computer.
- Request short-lived daemon credentials.
- Start the official local-execution daemon.
- Send startup data through Node IPC.
- Renew credentials and restart the daemon when necessary.
This project performs only those management tasks. It starts the official daemon with ELECTRON_RUN_AS_NODE=1, which does not create an Electron window or renderer.
Grok Bot service
|
| authenticated internal protocol
|
grokbot-headless controller
|
| Node IPC bootstrap and supervision
|
official local-exec-daemon
|
| approved commands and file operations
|
Linux user account
- browser-link OAuth with PKCE
- machine identity creation
- daemon and user-computer credential minting
- automatic credential renewal
- official daemon IPC bootstrap
- supervisor heartbeat
- repeated daemon restart handling
- local compatibility checks
- an authenticated remote protocol check
- a systemd user service
- the Grok Bot application or daemon
- a replacement Grok Bot model or service
- a local chat user interface
- root access
- automatic approval of local actions unless you select
policy always - a guarantee that future internal protocols will remain compatible
- Linux
- Node.js 20 or newer
- systemd user services
- the official Grok Bot Linux application
- a Grok Bot account with local-computer access
The default application location is:
/opt/Grok Bot
The current compatibility data lists the official Grok Bot Linux package 0.30.0 as tested. A different version can still work if all structural and remote protocol checks pass.
Clone the public repository:
git clone https://github.com/andreanjos/grokbot-headless.git
cd grokbot-headlessInstall the controller and enable its systemd user service:
./install.shThe installer runs a local compatibility check before it changes installed files. It does not start the service because account credentials do not exist yet.
Authenticate:
grok-bot-headless loginThe command prints a one-time URL. Open the URL in any browser and complete authentication. Do not share the URL or the resulting credential files.
Select an execution policy:
grok-bot-headless policy askStart the service:
systemctl --user start grok-bot-headlessVerify it:
grok-bot-headless check
grok-bot-headless statusIf your shell cannot find grok-bot-headless, start a new shell or use:
~/.local/bin/grok-bot-headlessThe installer enables the user service. To let the user service start during boot before desktop login, enable systemd lingering once:
sudo loginctl enable-linger "$USER"The policy controls how the official daemon handles local tool requests. The command registers the machine and synchronizes the same policy with the backend machine roster. Run it once after login and before the first service start. It is the only command that registers the machine.
| Policy | Behavior | Recommended use |
|---|---|---|
ask |
Ask before local actions. | Normal use. |
always |
Run local actions without an individual approval prompt. | Dedicated or isolated hosts only. |
never |
Reject local actions. | Disable remote local-computer access. |
Set a policy with:
grok-bot-headless policy <always|ask|never>
systemctl --user restart grok-bot-headlessCaution
policy always lets Grok Bot run commands and access files as your Linux user without an individual prompt. If that user has passwordless sudo, a remote command can also gain root access.
| Command | Purpose |
|---|---|
grok-bot-headless login |
Complete browser-link OAuth and save account credentials. |
grok-bot-headless run |
Run the controller in the foreground. The systemd service normally uses this command. |
grok-bot-headless status |
Show machine, daemon, policy, and credential-expiry state as JSON. |
grok-bot-headless check --local |
Check the installed package without network access or account credentials. |
grok-bot-headless check |
Check the installed package, authentication, and remote credential protocol. |
grok-bot-headless policy <value> |
Set always, ask, or never. |
grok-bot-headless logout |
Stop the managed service and remove OAuth and active daemon credentials. |
logout refuses to remove credentials if a directly started daemon remains active. Stop that foreground process first.
Run the full check after each official Grok Bot package update:
grok-bot-headless checkThe full check:
- Reads the exact installed package version.
- Confirms that the official application and archive exist.
- Resolves the expected daemon entry point from the installed archive.
- Validates the saved OAuth credential format.
- Refreshes OAuth credentials when required.
- Requests both required runtime credentials from the current backend and writes them to the runtime data directory. A running service replaces this file again at its next renewal.
It does not send a shell command or file request through Grok Bot.
Example:
{
"compatible": true,
"installedVersion": "0.30.0",
"testedVersion": true,
"daemonEntryPoint": "verified",
"authentication": "verified"
}Use the local-only check before login or without network access:
grok-bot-headless check --localThe installer runs the local check before installation. The systemd service runs it as an ExecCondition before each start. If this condition fails, the service stays stopped and does not enter its restart loop.
testedVersion: false means that the exact package version is not in the tested-version list. It does not mean that the check failed. The structural and remote checks determine the compatibility result.
cd /path/to/grokbot-headless &&
git pull --ff-only &&
./install.sh &&
grok-bot-headless check &&
systemctl --user restart grok-bot-headlessThe update keeps OAuth credentials, the machine identity, runtime data, and the selected policy.
grok-bot-headless check &&
systemctl --user restart grok-bot-headless &&
systemctl --user status grok-bot-headless --no-pagerIf the check fails, do not bypass it. Record the installed Grok Bot version and the redacted error, then open a GitHub issue.
Show service state:
systemctl --user status grok-bot-headless --no-pagerRestart or stop the service:
systemctl --user restart grok-bot-headless
systemctl --user stop grok-bot-headlessFollow logs:
journalctl --user -u grok-bot-headless -fShow recent logs:
journalctl --user -u grok-bot-headless -n 100 --no-pagerThe service uses Restart=on-failure. The controller also restarts the daemon if the daemon exits while the controller remains active.
The source remains in the directory where you ran git clone. This README uses /path/to/grokbot-headless when that location is not known.
~/.local/bin/grok-bot-headless
~/.local/lib/grok-bot-headless/grok-bot-headless.mjs
~/.config/systemd/user/grok-bot-headless.service
~/.config/grok-bot-headless/environment
~/.config/grok-bot-headless/credentials.json
~/.config/grok-bot-headless/machine.json
~/.local/share/grok-bot-headless/
Credential and environment files use owner-only permissions. New private directories use owner-only access.
OAuth credentials are stored as plaintext JSON because a portable headless Linux host does not always have a desktop keyring. Protect the user account, home directory, backups, and process environment. Never commit these directories or attach their contents to an issue.
Use the least privilege that supports your work:
- Start with
policy ask. - Use a dedicated Linux account or isolated host when possible.
- Do not give the service user passwordless
sudounless remote root access is intentional. - Keep the official Grok Bot package and this controller current.
- Review service logs and active sessions.
- Run
grok-bot-headless logoutwhen you remove the host from service.
Do not publish:
- OAuth access or refresh tokens
- one-time login URLs
- daemon credentials
- authorization headers
- complete machine identity files
- unredacted service logs
Use GitHub private vulnerability reporting for security defects. See SECURITY.md.
If the official package uses different paths, pass them during installation:
GROK_BOT_BINARY=/path/to/grok-bot \
GROK_BOT_DAEMON_SCRIPT=/path/to/local-exec-daemon/main.cjs \
./install.shThe installer saves these paths in:
~/.config/grok-bot-headless/environment
For direct CLI development runs, export the same values in the shell.
API and website URLs can also be overridden for development:
export CURSOR_API_BASE_URL=https://api.example.test
export CURSOR_WEBSITE_URL=https://example.testThe backend endpoint receives OAuth credentials. Use only a server that you control and trust. The controller requires HTTPS.
For a local development server only, HTTP can be enabled for localhost, 127.0.0.1, or ::1:
export GROK_BOT_ALLOW_INSECURE_LOCALHOST=1Confirm that ~/.local/bin is in PATH:
printf '%s\n' "$PATH"You can run the installed command directly:
~/.local/bin/grok-bot-headless statusRun:
grok-bot-headless loginThen restart the service:
systemctl --user restart grok-bot-headlessCollect these results:
grok-bot-headless check --local
systemctl --user status grok-bot-headless --no-pager
journalctl --user -u grok-bot-headless -n 100 --no-pagerRemove tokens, credentials, machine IDs, email addresses, and private file contents before you share output.
Check the service and daemon:
grok-bot-headless status
systemctl --user is-active grok-bot-headlessThen run the authenticated check:
grok-bot-headless checkIf authentication has expired, run grok-bot-headless login again.
Check lingering:
loginctl show-user "$USER" -p LingerEnable it if necessary:
sudo loginctl enable-linger "$USER"No third-party Node.js runtime dependency is required.
Run the complete test suite:
npm testRun syntax and unit-file checks:
node --check grok-bot-headless.mjs
bash -n install.sh uninstall.sh bin/grok-bot-headless test/install.test.sh
systemd-analyze --user verify grok-bot-headless.serviceThe test suite includes pure protocol-helper tests, an isolated installer test, and an end-to-end test. The end-to-end test runs the CLI against a fake backend server and a fake daemon on the loopback interface. The tests use fake application and systemd commands. They do not contact Grok Bot.
Before you submit a change:
- Keep the controller separate from proprietary Grok Bot code.
- Do not add extracted application bundles or credentials.
- Add a deterministic test for protocol changes when possible.
- Run the complete test suite.
- Explain the tested official package version in the pull request.
Remove the controller and service, but keep credentials and runtime data:
./uninstall.shRemove the controller, service, credentials, machine identity, policy, and runtime data:
./uninstall.sh --purgeThe uninstall command does not remove the official Grok Bot application.
This is an independent, unofficial project. It is not endorsed by xAI, SpaceXAI, Cursor, or Anysphere.
Grok Bot and related names can be trademarks of their owners. Use the official application and service under their applicable terms.
The original controller code in this repository is available under the MIT License.