Repository navigation
Expand file tree
/
Copy pathconfig.example.json
More file actions
139 lines (119 loc) · 9.72 KB
/
Copy pathconfig.example.json
File metadata and controls
139 lines (119 loc) · 9.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// pairing-buddy config. JSON with // comments. The daemon takes a change as you save it; `pair doctor` checks it.
{
// How often Pair speaks unasked: "quiet", "normal" or "chatty".
"level": "normal",
// Your verdicts on Pair's unasked remarks (useful or not; ignored counts as not) tune each trigger's bar
// and the level's budget, within fixed bounds. `pair stats` shows how. false keeps the level's defaults.
"autoTune": true,
// Once the session has a goal, Pair proposes it as two to four steps and says "done: X; next: Y" when one lands.
// false proposes none; /plan in the chat still sets steps of your own.
"plan": true,
// While you work, Pair asks the Watcher's model for one token every 4 min, so a server that unloads idle
// models (many do after 5 min) still has it loaded when a remark needs scoring. false turns it off; with an
// "anthropic" or a "provider" Watcher it is off unless set.
// "keepWarm": false,
// While the Watcher's calls take 1.5 s or more, Pair asks it about fewer kinds of moment: the ones you can see on
// your screen go first, the ones you cannot (a failure you missed, a crash) never. false asks about every kind.
"watcherPace": true,
// Tests Pair runs in its own pane (herdr's, or a :terminal in Neovim) when you save a source file in a project: the
// project's folder and the command, or {"command": ..., "timeoutSeconds": 600, "affected": false} for a longer cap,
// or the whole command on every save. Most runners also put each test's result on its line (go test -json,
// jest --json, cargo test, pytest -v).
// "testOnSave": {"~/src/shop": "go test -json ./..."},
// The work board's command, Shepherdr's: a session takes its goal from the board task of its branch (matched by the
// repo's space and the number), the context card (:Pair context) shows the task, the chat's header counts the space's
// tasks, and /gen board composes a task to add. null turns it off; without the command, nothing is read.
// "board": "shepherdr",
// A project is a git root (each git worktree is one). In a monorepo, these folders are projects of their own;
// "<folder>/*" makes each folder in it one.
// "sessionRoots": ["~/src/shop/packages/*"],
// Your other agents: when one needs you, is ready to merge or is done, Pair says so in one line at your next
// breakpoint (a save, a run that ended, a stop to look). It reads herdr's agents and the board above, if there is
// one. false turns the relay off.
// "agents": false,
// Pair's panel in the Herdr window (docs/herdr.md): the daemon opens a port on 127.0.0.1 for it, with a token only you
// can read, where the Herdr window is installed ("auto"). false keeps the chat in a terminal there; true opens it anyway.
// "herdrPanel": "auto",
// What :Pair tasks runs for each task you say yes to, in the project, as a list of words: {title} and {description}
// are put in as whole words, never through a shell. Without it, the tasks are copied as a Markdown checklist.
// "taskCommand": ["gh", "issue", "create", "--title", "{title}", "--body", "{description}"],
// What one /gen request may do at most (see docs/gen.md); they stop a model that loops. The note its brief has
// when you pinned none (/brief), when the project has it; null for the goal and the board task only. The days a
// /gen try folder or a scaffold's copy stays, whether their runs reach the network, and where a /gen scaffold goes:
// "tree", a copy in Pair's data folder, or "worktree", a git worktree on a branch gen/<n>. The defaults:
// "gen": {"limits": {"files": 40, "lines": 4000, "commands": 8, "minutes": 10}, "brief": "NOTES.md", "keepTries": 7, "network": false, "scaffold": "tree"},
// Search by meaning (Alt-s in Neovim, see docs/meaning.md): its word search works at once; meaning needs
// EmbeddingGemma 2 and its runtime LiteRT-LM, which :Pair find on downloads and installs once (a venv in Pair's data
// folder). It runs on this many cores, at low priority. "python" only for a Python of your own that already has
// litert-lm-api: with it set, Pair installs nothing. "index": "project" keeps the index in .pair/ of the repository
// (listed in .git/info/exclude) rather than Pair's data folder; false turns it all off for good.
// "meaning": {"threads": 2, "index": "data"},
// Or an embedding model of your own behind an OpenAI-compatible /v1/embeddings, instead of EmbeddingGemma 2:
// "embedding": {"api": "openai", "baseUrl": "http://127.0.0.1:8080/v1", "model": "jina-embeddings-v2-base-code"},
// Optional: a decision model that reorders search by meaning's first ten pieces once a list is settled (/find, the
// search tool, a picker after you stop typing), such as LiquidAI's d1-2B on llama.cpp. A search waits "timeoutMs" for
// it at most; down or slow, the order stays (see docs/meaning.md#rerank).
// "rerank": {"api": "system-one", "baseUrl": "http://127.0.0.1:8080/v1", "model": "d1-2B", "top": 10, "timeoutMs": 3000},
// Or a list, best first: a GPU's model when it is up (waited for 1 s), else the CPU's.
// "rerank": [
// {"api": "system-one", "baseUrl": "http://127.0.0.1:8081/v1", "model": "gpu-model", "top": 15, "timeoutMs": 1000},
// {"api": "system-one", "baseUrl": "http://127.0.0.1:8080/v1", "model": "d1-2B"}
// ],
// Pair's own pane, where Scout's commands and the tests on save run (see docs/scout.md#pairs-pane): your rc file
// for its aliases, functions and PATH (true is ~/.bashrc), and the bubblewrap sandbox: "auto" where bwrap works,
// true always, false never; inside it only the project and `writable` keep what is written, and no network unless allowed.
// "scoutPane": {"rc": "~/.bashrc", "sandbox": "auto", "network": false, "writable": ["~/.cache"]},
// One model for both roles: the Watcher asks it for one number without thinking, so it stays fast; the Partner
// asks it with thinking. Its server needs to hold only this model, and may answer one request at a time: the
// Watcher then waits while the Partner works, and your questions go first.
"model": {
"api": "openai", // "openai" (any OpenAI-compatible server) or "anthropic"; or a "provider"
"baseUrl": "http://localhost:8080/v1",
"model": "your-model"
// "contextWindow": 32768, // Pair asks the server what it serves; set it where the server does not say (32768 then)
// How much the Partner thinks, by kind of turn (these are the defaults), or one level for all; "off" switches
// it off. Levels: off, minimal, low, medium, high, xhigh. A remark comes a few seconds later; that is fine.
// "thinking": {"navigator": "medium", "scout": "medium", "driver": "medium", "remark": "low", "gen": "medium"},
// "reasoning": false, // for a model that cannot think: Pair then sends it no thinking level
// How the server takes thinking: its chat template's switch, and the level as reasoning_effort or a budget
// (without that, every level is just "on"). `pair doctor --thinking` finds it and prints the line:
// "compat": {"thinkingFormat": "...", "supportsReasoningEffort": true},
// "samplingParams": {"temperature": 0.3}, // steadier Partner answers when the server's default is high
// "auth": "my-server" // a key stored by `pair auth login my-server`; or "apiKeyEnv", "apiKey", "apiKeyFile"
// A cloud model instead: a provider pi-ai knows, with a subscription login or an API key from
// `pair auth login PROVIDER` (`pair auth list` lists the providers, `pair auth models PROVIDER` their models).
// A subscription's requests count against its plan's limits, and its terms decide whether a tool like this
// may use it (see "Logins and keys" in docs/models.md).
// "provider": "anthropic", "model": "your-cloud-model"
}
// Or a model for each role, in place of "model": a small fast Watcher (under 1 s per answer) and a larger
// Partner. The Watcher never thinks ("reasoning": true on a model that thinks by default lets Pair switch it off).
// "watcher" may also be "same as partner".
// "models": {
// "watcher": {"api": "openai", "baseUrl": "http://localhost:8080/v1", "model": "your-small-model"},
// "partner": {"api": "openai", "baseUrl": "http://localhost:8081/v1", "model": "your-larger-model"}
// }
// Optional: a decision (classifier) model the speak gate asks, with probabilities, whether a moment is worth a
// remark now, so fewer moments go to the Watcher. Without it the Watcher's score and the bar decide; down or slower
// than "timeoutMs", Pair goes by them at once (see docs/decision.md). `pair auth models openrouter` lists them.
// "decision": {"provider": "openrouter", "model": "typesafe/jev-1.14", "timeoutMs": 1500},
// Or a gateway: {"api": "openai" (OpenAI's Decisions API), "system-one" or "llama-cpp", "baseUrl": "...", "model": "..."}
// Push-to-talk: hold Alt-t in Neovim and ask aloud. LFM3-Omni hears and reads answers aloud on the CPU, after
// :Pair voice on downloads it (4.0 GB, once; see docs/voice.md). "talk": true reads every answer aloud.
// "voice": {},
// Or whisper.cpp hears, on the CPU:
// "voice": {
// "model": "~/src/whisper.cpp/models/ggml-base.en.bin",
// "whisper": "whisper-cli", // the program, on PATH or a path
// "speak": "espeak-ng" // reads an answer aloud, only when you are away from the editor
// },
// Or through OpenRouter, without whisper.cpp: a transcription model hears, a speech model reads aloud.
// "voice": {
// "openrouter": {
// "apiKeyFile": "~/.config/openrouter.key",
// "hear": "openai/whisper-large-v3-turbo",
// "speak": {"model": "x-ai/grok-voice-tts-1.0", "voice": "eve"}
// }
// },
// Also: "typingPauseMs" (default 2000), "socket" and "dataDir" (see docs/config.md).
}