No description
  • Shell 83.5%
  • TypeScript 15.6%
  • Dockerfile 0.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-13 22:22:06 +02:00
addons added subagents addon 2026-08-13 22:14:50 +02:00
bin added subagents addon 2026-08-13 22:14:50 +02:00
defaults Changed deepseek models to Luna 2026-08-13 22:22:06 +02:00
docker Initial pis wrapper 2026-06-03 20:26:35 +02:00
.gitignore Initial pis wrapper 2026-06-03 20:26:35 +02:00
install.sh added subagents addon 2026-08-13 22:14:50 +02:00
package.json Distribute bundled extensions as a Pi package 2026-07-25 23:24:33 +02:00
README.md Changed deepseek models to Luna 2026-08-13 22:22:06 +02:00
VERSION Refactor CLI around access profiles 2026-07-01 21:31:31 +02:00

pis

pis is a small user-level wrapper for the Pi coding agent with explicit access profiles.

The important choice is not “which backend”, but “how much access should the agent get?”

Profiles

pis [args...]          # default: project profile
pis project [args...]  # Docker sandbox, current project mounted read/write
pis inspect [args...]  # host read-only inspection: read/grep/find/ls only
pis host [args...]     # unrestricted host runtime, full access as your user

Recommended use:

  • pis / pis project for normal project work.
  • pis inspect when you want the agent to look around the host without write or shell access.
  • pis host only when you intentionally want full system-wide access.

project uses Docker internally. inspect and host use a Pi npm runtime managed by pis under ~/.local/share/pis/runtime.

Install

From a local checkout:

git clone <repo-url> pis
cd pis
./install.sh

Install/update wrapper files, the bundled package catalog, and managed configuration without installing runtimes or Pi packages:

./install.sh --no-build

The installer is idempotent. It updates the wrapper, Dockerfile, package catalog, managed global instructions, and pi-subagents defaults, but it does not delete sessions or overwrite an existing ~/.config/pis/config. The repository versions of defaults/AGENTS.md and defaults/subagents-config.json are authoritative. The subagent model fragment is merged into PIS_AGENT_DIR/settings.json, preserving unrelated Pi settings and unrelated fields in each agent override.

Usage

pis                         # project profile, pass args to pi
pis --version               # pi --version in project profile
pis project --version       # same, explicit project profile
pis inspect "read /etc/hosts"
pis host "help me debug my shell config"

pis setup                   # install/build project + host runtimes and packages
pis setup --no-build        # create directories/config only
pis setup project           # build Docker runtime and install packages
pis setup host              # install host runtime and packages

pis runtime update          # update Docker image + host runtime
pis runtime update project  # update Docker image only
pis runtime update host     # update host runtime only
pis runtime versions        # show wrapper/project/host versions

pis doctor                  # check setup for all profiles
pis info                    # print resolved config for current project
pis sessions-path           # print current project's host session dir
pis help                    # wrapper help

pis runtime ... manages the project and host Pi runtimes. Plain Pi package commands pass through to Pi in the default project profile:

pis install npm:@foo/pi-tools
pis update --extensions
pis list

Bundled add-ons

pis setup installs four npm packages and this repository as a Pi git package:

npm:pi-web-access
npm:pi-btw
npm:pi-codex-limit
npm:pi-subagents
git:https://github.com/MrQvic/pis.git

The git package exposes the two extensions under addons/extensions/. Pi stores all five packages in the shared agent directory, so project and host profiles load the same resources. The legacy copied extension files are removed after a successful setup.

After add-on changes are pushed, update every configured machine through Pi's normal package mechanism, then reload a running session:

pis update --extensions
# Run /reload inside an existing Pi session, or restart it.

./install.sh --no-build refreshes the wrapper, package catalog, and managed configuration, but it does not install Pi packages. A new installation still needs pis setup (or ./install.sh) once to install and register the packages.

Paths

~/.local/bin/pis                         executable
~/.config/pis/config                     user config
~/.config/pis/docker/Dockerfile          project profile Dockerfile
~/.local/share/pis/                      data root
~/.local/share/pis/agent/                shared Pi agent state, instructions, add-ons
~/.local/share/pis/bundled-packages.txt         package catalog installed by pis
~/.local/share/pis/managed-AGENTS.md            source for global instructions
~/.local/share/pis/managed-subagents-config.json operational subagent defaults
~/.local/share/pis/managed-subagents-settings.json model-routing settings fragment
~/.local/share/pis/sessions/<key>/               per-project sessions
~/.local/share/pis/runtime/              host/inspect npm runtime
~/.local/share/pis/docker-home/          project Docker HOME
~/.local/share/pis/project-map.json      project key -> host path map

State model:

  • agent/ is shared by all profiles. Project Docker mounts it at the same absolute path as on the host and all profiles pass it as PI_CODING_AGENT_DIR.
  • defaults/AGENTS.md in the repository is the authoritative source for global instructions. The installer stages it as managed-AGENTS.md; pis setup copies it to the resolved agent directory, replacing the previous file.
  • defaults/subagents-config.json is copied to PIS_AGENT_DIR/extensions/subagent/config.json. The model routing from defaults/subagents-settings.json is deep-merged into the global Pi settings.json; repository values win only for keys present in the fragment.
  • sessions/<key>/ is per project. Project Docker mounts only the current project's session directory at the same absolute path as on the host and all profiles pass it as PI_CODING_AGENT_SESSION_DIR.
  • Project Docker bind-mounts the current project at the same absolute path as on the host and uses that as its workdir. This keeps Pi's stored session cwd identical between profiles, so --continue/--resume see the same sessions.
  • runtime/ contains the host/inspect npm install of Pi.
  • docker-home/ is only the Docker profile's HOME. It is not the source of truth for Pi agent state.

No previous state is imported automatically. pis owns its state under ~/.local/share/pis.

Configuration

Subagent defaults

pis setup caps concurrent top-level async runs at two, defaults parallel workflows to two concurrent children, stores run artifacts with the Pi session instead of in the working tree, and applies this model routing:

Agent Model Thinking
scout openai-codex/gpt-5.6-luna low
researcher openai-codex/gpt-5.6-luna medium
worker openai-codex/gpt-5.6-luna high
delegate openai-codex/gpt-5.6-luna high
reviewer openai-codex/gpt-5.6-sol high
oracle openai-codex/gpt-5.6-sol xhigh

Other agents default to GPT-5.6 Luna with medium thinking. Run /reload after setup when changing these defaults inside an existing Pi session.

Wrapper configuration

Default config file:

# ~/.config/pis/config
# PIS_IMAGE=pis:latest
# PIS_AGENT_DIR=~/.local/share/pis/agent
# PIS_RUNTIME_DIR=~/.local/share/pis/runtime

Useful environment overrides:

PIS_CONFIG_DIR=~/.config/pis
PIS_DATA_DIR=~/.local/share/pis
PIS_AGENT_DIR=~/.local/share/pis/agent
PIS_RUNTIME_DIR=~/.local/share/pis/runtime
PIS_PI_PACKAGE=@earendil-works/pi-coding-agent@latest
PIS_PI_CMD=/custom/path/to/pi
PIS_IMAGE=pis:latest
PIS_SESSION_DIR=~/.local/share/pis/sessions
PIS_DOCKER_HOME=~/.local/share/pis/docker-home
PIS_MEMORY=2g
PIS_CPUS=2

PIS_BACKEND from older versions is ignored. Use profiles instead: project, inspect, or host.

Safety notes

The project profile does not mount the Docker socket and does not use privileged mode. It uses a read-only container filesystem, drops capabilities, and limits pids/CPU/RAM.

The current working directory is still a read/write bind mount. Pi can modify or delete files in the current project. Use git/worktrees/WIP commits when working on important changes.

The inspect profile runs on the host but forces:

--no-extensions --tools read,grep,find,ls

It cannot run bash or use edit/write. Explicit tool/extension override flags, --export, and Pi package/config commands that can modify state are rejected. It still runs as your user and can read files your user can read.

The host profile has no pis sandbox. It runs pi as your user in the current directory and can access anything your user account can access.

Development

Source layout:

addons/extensions/
addons/packages.txt
defaults/AGENTS.md
defaults/subagents-config.json
defaults/subagents-settings.json
bin/pis
docker/Dockerfile
install.sh
package.json
README.md
VERSION

After wrapper, package-catalog, global-instruction, or subagent-default changes, reinstall the managed files locally:

./install.sh --no-build

After extension changes are pushed, update the installed git package:

pis update --extensions