@sneub/pair 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shane
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,169 @@
1
+ # pair
2
+
3
+ A personal AI assistant powered by Claude. Connects Telegram and Slack to
4
+ Claude with persistent memory, a workspace of notes, and custom tools — all
5
+ running as a long-lived daemon on your own machine.
6
+
7
+ ## Install
8
+
9
+ Pair is a Bun CLI. Install it globally:
10
+
11
+ ```bash
12
+ bun install -g @sneub/pair
13
+ ```
14
+
15
+ ## Quick start
16
+
17
+ ```bash
18
+ mkdir my-agent && cd my-agent
19
+ pair init # scaffolds config.json, workspace/, .env, .gitignore
20
+ # edit .env with your API keys / bot tokens
21
+ pair run # foreground
22
+ pair run -d # background daemon
23
+ ```
24
+
25
+ `pair init` is non-interactive and creates everything in the current directory.
26
+ After editing `.env`, point it at Telegram or Slack and start chatting.
27
+
28
+ For an interactive setup that writes to `~/.pair/` instead, use `pair setup`.
29
+
30
+ ## Commands
31
+
32
+ | Command | Description |
33
+ |---|---|
34
+ | `pair init` | Bootstrap a new agent directory in the current working dir (non-interactive) |
35
+ | `pair setup` | Interactive setup wizard — creates config, workspace, prompts for keys |
36
+ | `pair doctor` | Run diagnostic checks on your configuration |
37
+ | `pair tool list` | Show packaged and user tools, and which are enabled |
38
+ | `pair tool enable <name>` | Enable a packaged tool by adding it to `config.tools.enabled` |
39
+ | `pair tool disable <name>` | Disable a packaged tool |
40
+ | `pair run` | Start Pair in the foreground (alias: `pair start`) |
41
+ | `pair run -d` | Start Pair as a background daemon |
42
+ | `pair stop` | Stop the running daemon (SIGTERM, then SIGKILL after 10s) |
43
+ | `pair status` | Show running state, workspace stats, and config summary |
44
+
45
+ ## Configuration
46
+
47
+ Pair stores its configuration under its resolved home directory:
48
+
49
+ 1. `$PAIR_HOME` — explicit override (used by Docker and multi-instance setups)
50
+ 2. `./config.json` in the current working directory → **local mode**
51
+ 3. `~/.pair/` → **global mode** (default)
52
+
53
+ Within that home directory, Pair reads `config.json` (non-secret settings)
54
+ and `.env` (secrets). Environment variables always override values from
55
+ `config.json`, so you can keep non-secret settings in JSON and inject
56
+ secrets at deploy time.
57
+
58
+ ### config.json
59
+
60
+ | Field | Type | Default | Description |
61
+ |---|---|---|---|
62
+ | `pair.sessionTimeoutMinutes` | number | `30` | Idle time before a session expires |
63
+ | `pair.logLevel` | string | `"info"` | `debug`, `info`, `warn`, `error` |
64
+ | `pair.model` | string | `"claude-sonnet-4-6"` | Claude model to use |
65
+ | `pair.workspaceDir` | string | `"~/.pair/workspace"` | Path to workspace directory |
66
+ | `pair.healthCheckPort` | number | _(unset)_ | Port for HTTP health check endpoint |
67
+ | `pair.authMode` | string | `"api-key"` | `"api-key"` or `"oauth"` (Claude Max/Pro) |
68
+ | `telegram.allowedUsers` | number[] | `[]` | Telegram user IDs allowed to interact |
69
+ | `slack.allowedUsers` | string[] | `[]` | Slack user IDs allowed to interact |
70
+ | `mcp.servers` | object | `{}` | MCP server configurations |
71
+ | `tools.enabled` | string[] | `["examples"]` | Packaged tool names to enable |
72
+
73
+ ### Environment variables
74
+
75
+ | Variable | Required | Description |
76
+ |---|---|---|
77
+ | `ANTHROPIC_API_KEY` | api-key mode only | Anthropic API key for Claude |
78
+ | `PAIR_AUTH_MODE` | No | `api-key` (default) or `oauth` (Claude Max/Pro) |
79
+ | `PAIR_API_KEY_HELPER` | No | Path to a script that outputs fresh credentials |
80
+ | `TELEGRAM_BOT_TOKEN` | No | Telegram Bot API token |
81
+ | `TELEGRAM_ALLOWED_USERS` | No | Comma-separated Telegram user IDs |
82
+ | `SLACK_BOT_TOKEN` | No | Slack bot OAuth token (`xoxb-...`) |
83
+ | `SLACK_APP_TOKEN` | No | Slack app-level token (`xapp-...`) |
84
+ | `SLACK_SIGNING_SECRET` | No | Slack signing secret |
85
+ | `PAIR_MODEL` | No | Override the Claude model |
86
+ | `PAIR_LOG_LEVEL` | No | Override the log level |
87
+ | `PAIR_WORKSPACE_DIR` | No | Override the workspace directory |
88
+ | `PAIR_HEALTH_PORT` | No | Override the health check port |
89
+ | `PAIR_HOME` | No | Override the Pair home directory |
90
+
91
+ ## Workspace
92
+
93
+ After `pair init`, your workspace lives at `./workspace/` (or
94
+ `~/.pair/workspace/` in global mode) and contains files Claude reads on every
95
+ turn:
96
+
97
+ - `SYSTEM.md` — base system prompt and personality
98
+ - `USER.md` — information about you
99
+ - `MEMORY.md` — persistent memory (Claude can update this)
100
+ - `tasks.md` — your current task list
101
+
102
+ Edit them freely — they're how you customize Pair's behavior.
103
+
104
+ ## Tools
105
+
106
+ Tools are the quickest way to add custom capabilities. You have two options:
107
+ enable one of the packaged tools that ship with Pair, or drop your own
108
+ executable into `<pair home>/tools/`.
109
+
110
+ **Enable a packaged tool:**
111
+
112
+ ```bash
113
+ pair tool list # see what's available
114
+ pair tool enable todoist # adds "todoist" to config.tools.enabled
115
+ echo "TODOIST_API_TOKEN=..." >> .env
116
+ pair stop && pair run -d
117
+ ```
118
+
119
+ **Write a custom tool** by dropping a file into `./tools/`:
120
+
121
+ ```bash
122
+ #!/usr/bin/env bash
123
+ # name: uk-holiday
124
+ # description: Return whether today is a UK bank holiday.
125
+ # usage: uk-holiday
126
+
127
+ curl -s https://www.gov.uk/bank-holidays.json | jq -r \
128
+ --arg today "$(date +%Y-%m-%d)" '
129
+ .["england-and-wales"].events
130
+ | map(select(.date == $today))
131
+ | if length > 0 then "yes — \(.[0].title)" else "no" end
132
+ '
133
+ ```
134
+
135
+ ```bash
136
+ chmod +x ./tools/uk-holiday
137
+ pair stop && pair run -d
138
+ ```
139
+
140
+ Now DM Pair _"is today a UK bank holiday?"_ and it'll run the tool. Any
141
+ language works (bash, Bun, Node, Python, Ruby). Pair parses a short header
142
+ comment at the top of each file for the description it shows to Claude.
143
+
144
+ ## MCP servers
145
+
146
+ Pair supports [Model Context Protocol](https://modelcontextprotocol.io/)
147
+ servers for extending Claude's capabilities. Configure them in `config.json`:
148
+
149
+ ```json
150
+ {
151
+ "mcp": {
152
+ "servers": {
153
+ "filesystem": {
154
+ "command": "npx",
155
+ "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
156
+ }
157
+ }
158
+ }
159
+ }
160
+ ```
161
+
162
+ ## Requirements
163
+
164
+ - [Bun](https://bun.sh) ≥ 1.1.0
165
+ - An Anthropic API key (or a Claude Max/Pro account for OAuth mode)
166
+
167
+ ## License
168
+
169
+ MIT
@@ -0,0 +1,22 @@
1
+ {
2
+ "pair": {
3
+ "sessionTimeoutMinutes": 30,
4
+ "logLevel": "info",
5
+ "model": "claude-sonnet-4-6"
6
+ },
7
+ "telegram": {
8
+ "enabled": true,
9
+ "allowedUsers": []
10
+ },
11
+ "slack": {
12
+ "enabled": false,
13
+ "allowedUsers": [],
14
+ "channels": []
15
+ },
16
+ "mcp": {
17
+ "servers": {}
18
+ },
19
+ "tools": {
20
+ "enabled": ["examples"]
21
+ }
22
+ }