A barebone sandbox for agentic coding based on UNIX user
Project description
A⁴U²: AI Agent As Another Unix User (aka agent-as-unix-user)
A barebone sandbox for agentic coding based on UNIX users.
TL;DR:
uv tool install agent-as-unix-user # Install this cli
au new # Create a new UNIX user for your IA agent
au mount add --rw ~/example # Expose `~/example` in `/home/agent/example`
# with read&write access
au run --env FOO=bar claude # Run claude (with an environ variable) as the agent UNIX user,
# with only access to `/home/agent`
UNIX has been designed from the ground to allow multiple users to securely share a single machine (remember the time when a terminal was a physical thing that was used to connect to a mainframe ? Yeah, me neither).
So instead of containers or VMs, agent-as-unix-user is a simple wrapper around standard UNIX commands to easily:
- Creates a dedicated UNIX user
- Give access to certain folders in read-only or read&write mode
- Undo all of this if needed ;-)
- Run commands as the UNIX user
With your IA agent running as a dedicate user, protection becomes trivial:
This gives you filesystem-level isolation with minimal overhead: the agent runs on the same host, but under a separate UID with controlled access.
Installation
Only Linux is supported for now (MacOS might be possible though, so PR welcome \o/).
pipx install agent-as-unix-user
# or with uv
uv tool install agent-as-unix-user
[!NOTE] agent-as-unix-user has the following requirements:
- Linux with ACL support
- A C compiler (for the setuid entrypoint)
sudoaccess (for user/group creation and setuid setup)
Recipes
The great thing about this approach is its simplicity and it compatibility with the UNIX ecosystem.
Example 1: limit CPU & RAM
Limit the agent to use at most 16Go of RAM and one-and-half cores on your machine.
systemctl set-property user-$(id -u agent).slice CPUQuota=150% MemoryMax=16G
Example 2: filter network traffic
Run an HTTP proxy locally with your filtering rules, then configure iptables:
# Redirect HTTP and HTTPS traffic from UNIX user `agent` to
# port 3128 (default port for Squid HTTP proxy)
iptables -t nat -A OUTPUT -m owner --uid-owner agent -p tcp --dport 80 -j REDIRECT --to-port 3128
iptables -t nat -A OUTPUT -m owner --uid-owner agent -p tcp --dport 443 -j REDIRECT --to-port 3128
# Allow DNS
iptables -A OUTPUT -m owner --uid-owner agent -p udp --dport 53 -j ACCEPT
# Block everything else for that user
iptables -A OUTPUT -m owner --uid-owner agent -j DROP
How it works
When you create an agent, agent-as-unix-user will:
- Create a UNIX user (e.g.
agent) and a group (su-as-agent) - Add your user to the group so you can interact with the agent's files
- Configure the agent's home directory with setgid + ACL defaults so files created by either user remain editable by both
- Compile and install a small setuid C binary (
/home/agent/su_as_agent) to execute command as the agent.
Note agent-as-unix-user is designed to be as transparent as possible by only using UNIX commands and displaying them as they are run:
$ uv run au new -a agent2
Create agent agent2 in /home/agent2 and configure group 'su-as-agent2'? [y/N]: y
$ sudo groupadd su-as-agent2
[sudo] password for touilleMan:
$ sudo useradd --shell /usr/bin/bash --no-user-group --create-home --home-dir /home/agent2 --gid su-as-agent2 agent2
$ sudo usermod --append --groups su-as-agent2 touilleMan
$ sudo chgrp su-as-agent2 /home/agent2
$ sudo chmod 2770 /home/agent2
$ sudo setfacl --modify default:group:su-as-agent2:rwx /home/agent2
$ sg su-as-agent2 -c 'tee /home/agent2/README.md'
$ sg su-as-agent2 -c 'mkdir -p /home/agent2/.config/agent-as-unix-user/su_as_agent-src'
$ sg su-as-agent2 -c 'tee /home/agent2/.config/agent-as-unix-user/su_as_agent-src/main.c'
$ sg su-as-agent2 -c 'tee /home/agent2/.config/agent-as-unix-user/su_as_agent-src/Makefile'
$ sg su-as-agent2 -c 'make -C /home/agent2/.config/agent-as-unix-user/su_as_agent-src'
make: Entering directory '/home/agent2/.config/agent-as-unix-user/su_as_agent-src'
cc -O2 -Wall -Wextra -Werror -DTARGET_UID=1003 -DTARGET_GID=1003 -o su_as_agent main.c
make: Leaving directory '/home/agent2/.config/agent-as-unix-user/su_as_agent-src'
$ sg su-as-agent2 -c 'mv --force /home/agent2/.config/agent-as-unix-user/su_as_agent-src/su_as_agent /home/agent2/su_as_agent'
$ sudo chown root:su-as-agent2 /home/agent2/su_as_agent
$ sudo chmod 4750 /home/agent2/su_as_agent
Created agent agent2
To run a command as an agent, au run my_command will itself uses /home/agent/su_as_agent that:
- Scrubs your environ variables (only
LANGandTERMare kept). - Drops all the groups inherited from the original user.
- Sets UID and GID to become the agent user.
Usage
Create a new agent
au new # creates an agent named "agent" (default)
au new --agent agentA # custom agent name
au new --yes # skip confirmation prompt
Requires root/sudo. Creates the UNIX user, group, home directory (with setgid + ACL), compiles the setuid entrypoint, and updates the config file.
Run a command as the agent
au run echo hello # run as default agent "agent"
au run --agent agentA -- code # run as a specific agent
au run --env API_KEY=xxx -- cmd # pass environment variables
Before executing, au run verifies the entrypoint binary hasn't been modified by comparing its SHA-256 hash against the stored fingerprint. Environment is scrubbed by default — only LANG and TERM are kept, plus any variables passed explicitly via --env.
Show agent info & health
au info # info for default agent "agent"
au info --agent agentA # info for a specific agent
Displays the agent's home directory, group, entrypoint path, ACL external accesses, and runs a healthcheck that verifies:
- UNIX user and group exist
- Home directory exists with setgid bit
- Default ACLs are configured
- Entrypoint exists and is executable
- Current user is a member of the agent's group
- ACL tooling is available on the system
List agents
au list
Lists all agents present in the configuration file.
Delete an agent
au delete # delete default agent "agent"
au delete --agent agentA # delete a specific agent
au delete --delete-home # also remove the home directory
au delete --yes # skip confirmation prompt
Requires root/sudo. Removes the UNIX user, group, and optionally the home directory. Resilient to partial state — if some resources are already gone, it skips them and continues.
Global options
--config, -C PATH Config file (default: ~/.config/agent-as-unix-user.toml)
--version Show version
-h, --help Show help
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agent_as_unix_user-2.1.0.tar.gz.
File metadata
- Download URL: agent_as_unix_user-2.1.0.tar.gz
- Upload date:
- Size: 17.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8fd564bcd9d163f5d6692f2b67fcef0897a14bc4508d54817c270064fa58da01
|
|
| MD5 |
e9733d970731d9369841466927fa358f
|
|
| BLAKE2b-256 |
1eee1ff62e73b6fa6bdf5a515e2909d6cc6e11fe7c033c230953a2ee2a5d5d5c
|
Provenance
The following attestation bundles were made for agent_as_unix_user-2.1.0.tar.gz:
Publisher:
ci-cd.yml on touilleMan/agent-as-unix-user
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agent_as_unix_user-2.1.0.tar.gz -
Subject digest:
8fd564bcd9d163f5d6692f2b67fcef0897a14bc4508d54817c270064fa58da01 - Sigstore transparency entry: 1573037065
- Sigstore integration time:
-
Permalink:
touilleMan/agent-as-unix-user@2fcfc1bf3377244175f94590c47fe3b2c10ac540 -
Branch / Tag:
refs/tags/v2.1.0 - Owner: https://github.com/touilleMan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci-cd.yml@2fcfc1bf3377244175f94590c47fe3b2c10ac540 -
Trigger Event:
push
-
Statement type:
File details
Details for the file agent_as_unix_user-2.1.0-py3-none-any.whl.
File metadata
- Download URL: agent_as_unix_user-2.1.0-py3-none-any.whl
- Upload date:
- Size: 24.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d9f530d5d07521d68b6c42f806019c422052bd01a9f416c64931896bba54743b
|
|
| MD5 |
14085c7335a5276b3dc9058839b4a32c
|
|
| BLAKE2b-256 |
7635986bb184f4b1dbaa4109ee3a6707eb56ef8e5b7096dc80d134eab3380f6a
|
Provenance
The following attestation bundles were made for agent_as_unix_user-2.1.0-py3-none-any.whl:
Publisher:
ci-cd.yml on touilleMan/agent-as-unix-user
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agent_as_unix_user-2.1.0-py3-none-any.whl -
Subject digest:
d9f530d5d07521d68b6c42f806019c422052bd01a9f416c64931896bba54743b - Sigstore transparency entry: 1573037104
- Sigstore integration time:
-
Permalink:
touilleMan/agent-as-unix-user@2fcfc1bf3377244175f94590c47fe3b2c10ac540 -
Branch / Tag:
refs/tags/v2.1.0 - Owner: https://github.com/touilleMan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci-cd.yml@2fcfc1bf3377244175f94590c47fe3b2c10ac540 -
Trigger Event:
push
-
Statement type: