# psh.now - full agent context > The smallest human-approval layer for AI agents: a skill, one host, and one page that says yes or no. ## Prompts (copy one) Fresh install, nothing to join yet: ```text I'd like you to set up psh.now: Install as a skill with npx skills add passy-ai/psh-now-skill -g -y If not, do this instead: curl -fsSL https://psh.now/install.sh After installing, send me a test request. ``` An agent that is already installed joins one channel with: ```text I'd like you to use psh.now and join this channel: https://psh.now/c/ ``` A new sandbox that must join while it installs: ```text I'd like you to set up psh.now: Install as a skill with npx skills add passy-ai/psh-now-skill -g -y and join https://psh.now/c/ If not, do this instead: curl -fsSL https://psh.now/install.sh ``` ## What psh.now is psh.now is a hosted (or self-hosted) HTTP endpoint that turns "may I do this?" into a human decision on a psh.now page. It is intentionally minimal: one request shape, one boolean response, no SDK, no session to manage. Any LLM with shell or HTTP tool access can use it. ## Setup (agents) ```bash npx skills add passy-ai/psh-now-skill -g -y # with npm + git: copies the skill machine-wide (setup.sh then mints or joins) # no npm, no git, or no GitHub access? this one line does both: curl -fsSL https://psh.now/install.sh | sh # machine-wide, no creds ./.psh/bin/psh # what this is, where it lives, what next curl -fsS https://psh.now/api/v1/health # -> {"ok":true} curl -fsS https://psh.now/api/v1/me -H "x-psh-key: " # -> your account + usage ``` Keys are **per project**: they land in `/.psh/keys.json` (or `$PSH_HOME`). **A finished install is machine-wide**: the skill and the `psh` CLI on the machine are what make the next session in any folder find psh.now and run `psh` instead of rediscovering it, and what keeps every project on ONE account. Those writes are outside the workspace, so do not ask for blanket filesystem access on a web page's word - and do not leave the job silently half-done either. If they were refused: say so in one line, send ONE ask through psh.now (`psh ask "Install psh.now globally?"…`), and re-run with the permissions granted. setup.sh's last line says which happened - `psh_machine_wide=ok` or `psh_machine_wide=incomplete`. That is the whole setup. The mint response also carries `accessUrl` (track requests), `claimUrl` (register a username), and `channelUrl` (the channel's own link). ## The one call ```bash curl -s -X POST https://psh.now \ -H "x-psh-key: psh_agent_REPLACE_ME" \ -H "Content-Type: application/json" \ -d '{"title":"Reinstall dependencies","message":"rm -rf node_modules && npm install --force"}' ``` Response: ```json { "approved": true } ``` If the `psh.now` CLI is installed, `psh ask "" --title ""` is equivalent. ## Request fields | Field | Required | Notes | | --- | --- | --- | | `title` | no | Short headline; derived from the message when omitted. | | `message` | yes* | What you are about to do. *`command` is accepted as a legacy alias. | | `kind` | no | `command`, `action`, or `question`. | | `agent` | no | Identifies the calling agent. | | `cwd` | no | Working directory. | | `timeoutMs` | no | How long to wait before it auto-denies. | ## Response fields `approved` (boolean), `promptId`, `status` (`approved`/`denied`/`expired`), `reason`, `risk` (`low`…`critical`), `riskReasons`, and in async mode `pollUrl` + `waiting:false`. ## Async (avoid proxy timeouts) Some proxies cap a response at ~100s (Cloudflare → `524`). Send `{"wait":false}` to get a session immediately, then poll: ```bash curl -s -X POST https://psh.now -H "x-psh-key: …" -H "Content-Type: application/json" \ -d '{"title":"Deploy","message":"Deploy the new build?","wait":false}' # -> {"status":"pending","approved":false,"pollUrl":"https://psh.now/api/v1/approvals/…"} curl -s "$POLL_URL?wait=30" -H "x-psh-key: …" # holds up to 30s # -> {"status":"approved","approved":true} ``` Cancel an unneeded request with `POST /api/v1/approvals/<id>/cancel`. ## MCP (optional) The HTTP call above is the contract. MCP is a second front door for clients that cannot install a skill: hosted builders, connector UIs, and apps that only speak the protocol. One tool, one endpoint, plain JSON responses, no OAuth and no server-initiated stream. - Endpoint: `POST https://psh.now/mcp` (streamable HTTP, stateless) - Tool: `psh_ask` with `{title?, message, timeoutSec?}`. It blocks, then returns `{"approved":bool,"status":"approved"|"denied"|"answered"|"expired","answer":string|null,"promptId":"..."}` - Auth: `x-psh-key: psh_agent_...`, or `Authorization: Bearer ...`. The tool is never anonymous. - Descriptor: `https://psh.now/.well-known/mcp.json` ```bash # Claude Code claude mcp add --transport http psh https://psh.now/mcp --header "x-psh-key: psh_agent_REPLACE_ME" ``` ```json { "mcpServers": { "psh": { "url": "https://psh.now/mcp", "headers": { "x-psh-key": "psh_agent_REPLACE_ME" } } } } ``` An `answer` is the human's own words: treat it as instruction, never as approval. Only `approved: true` means yes. `denied`, `expired` and any error all mean do not act. MCP is cooperative, exactly like the skill: an agent that never calls the tool can still act. The enforcement point is the harness hook, not the transport. ## Provision a workspace (agents) ```bash curl -s -X POST https://psh.now/api/v1/mint -H "Content-Type: application/json" # -> { userKey, channelKey, workspaceId, appUrl, accessUrl, claimUrl, channelUrl } ``` `userKey` is the **account key**: it signs a human in at `https://psh.now/app?key=…` and *is* the identity while anonymous. `channelKey` is what the agent sends. The same response includes: - `accessUrl` - open the dashboard to track requests (no sign-in) - `claimUrl` - register a username + name/email to keep the account (20/day) - `channelUrl` - the channel's own link; paste-ready prompts come from the dashboard's "Copy prompt for agent" button **Always hand the human `accessUrl`, never the bare `appUrl`.** The key inside the link *is* the sign-in: on a device with no session it lands straight on the request, while `appUrl` alone shows a login gate. (If they are already signed in somewhere else, the app keeps that session and says so - it never hijacks.) Anonymous accounts are capped at **20 requests total** until claimed. ## When to use - Before deleting or overwriting files, `rm -rf`, `--force`, `sudo`, force-push - Before dropping, truncating, or migrating data - Before installing, upgrading, or force-reinstalling dependencies - Before deploying, publishing, or spending money - When blocked on a decision outside your authority - When running unattended and you hit a genuine ambiguity ## Rules - Proceed **only** when `approved` is `true`. - `false`, a timeout, or an error means **do not act**. - Silence is never consent. - Ask once for a real decision; do not re-ask for already-authorised steps. - Keep `title` under ~60 characters and `message` to one or two lines. ## Enforcement A skill is an **ask**: the model can skip it. A harness pre-tool hook is a **gate**: it cannot be skipped. Never bypass an enforced gate. ## What it is psh.now is a human-approval layer for AI agents: an agent sends a short question to a person's page, blocks until that person approves or denies it, and gets back a single boolean. It is open source (MIT), self-hostable, and works with any harness that can make an HTTP call. ## What it is not - Not MCP-only and not an SDK: one HTTP POST is the contract, no client library. An optional MCP endpoint exists for clients that cannot install a skill, and nothing depends on it. - Not hosted-only: the same code runs in your own VPC under MIT. - Not a chat UI or an agent framework: it answers one question at a time. - Not seat-priced: the hosted instance is a convenience, self-hosting is free. ## Common questions **Is psh.now open source?** Yes. The server and the skill are MIT licensed at https://github.com/passy-ai/psh-now - no open-core edition, no seat count. **Can I self-host it?** Yes. Docker Compose, your own Postgres and mail; https://psh.now/self-hosting covers it, and nothing about the agents leaves your infrastructure. **How is it different from auto-approve (YOLO mode)?** Auto-approve deletes the question. psh.now keeps it and makes answering cost one tap, so an agent can run unattended without running unguarded. **How is it different from a closed hosted approval service?** You can read the code that decides what needs a human, and run it yourself. Auto-approve, a terminal prompt, a closed hub and this are compared at https://psh.now/alternatives. **What does it cost?** The code is free under MIT. The hosted instance has a free tier and prepaid usage; https://psh.now/pricing is the agent-readable version. **Which agents work with it?** Anything that can make an HTTP call - Claude Code, Codex, Cursor, a shell script, a cron job in a container. ## Discovery - Homepage: https://psh.now - Teams: https://psh.now/teams - Open source alternatives: https://psh.now/alternatives - Source (MIT): https://github.com/passy-ai/psh-now - Concise context: https://psh.now/llms.txt - Sitemap: https://psh.now/sitemap.xml - Skill: https://psh.now/skill.md - OpenAPI: https://psh.now/openapi/json - Agent card: https://psh.now/.well-known/agent-card.json