@adaptiqai/code 0.0.0-stage → 0.1.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/.claude-plugin/plugin.json +12 -0
- package/.mcp.json +10 -0
- package/DESIGN.md +262 -0
- package/README.md +122 -2
- package/bin/adaptiqai-code +50 -0
- package/hooks/hooks.json +41 -0
- package/lib/index.js +31912 -0
- package/package.json +52 -3
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "adaptiqai-code",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "AdaptiqAI Code in Claude Code: the whole repository compiled into AdaptiqAI's memory and kept current from git, so the agent and every sub-agent ask it (code_ask, code_find, code_impact) instead of searching files.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "AdaptiqAI",
|
|
7
|
+
"url": "https://adaptiqai.com"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://adaptiqai.com",
|
|
10
|
+
"license": "UNLICENSED",
|
|
11
|
+
"keywords": ["adaptiqai", "repository", "codebase", "memory", "sub-agents"]
|
|
12
|
+
}
|
package/.mcp.json
ADDED
package/DESIGN.md
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# AdaptiqAI Code: design and measurements
|
|
2
|
+
|
|
3
|
+
AdaptiqAI Code compiles a whole git repository into AdaptiqAI's memory (an
|
|
4
|
+
NCM collection), keeps it current from git, and lets a coding agent and its
|
|
5
|
+
sub-agents ask it instead of searching files.
|
|
6
|
+
|
|
7
|
+
## Modules
|
|
8
|
+
|
|
9
|
+
Every capability is one contract in `src/kernel/types.ts` and one or more
|
|
10
|
+
modules behind it, so a better method replaces a module and nothing else.
|
|
11
|
+
|
|
12
|
+
| Contract | Module | What it does |
|
|
13
|
+
| --- | --- | --- |
|
|
14
|
+
| `RepoSource` | `source/git.ts` | Files of HEAD plus the working tree, blob ids (from git's index when unchanged, else `hash-object`), churn from `git log`. |
|
|
15
|
+
| `FileFilter` | `filter/` | Binary, too large, lockfiles, generated, vendored, secrets (the whole file is kept out), `.adaptiqignore`, empty. |
|
|
16
|
+
| `Layout` | `layout/churn.ts`, `layout/path.ts` | Compile order: stable files first, so edits land late in the causal chain. |
|
|
17
|
+
| `Deriver` | `map/derive.ts` | `repo-map.md` (ranked definitions, Aider-style PageRank) and `relations.md` (imports, importers, tests), compiled with each rebuild. |
|
|
18
|
+
| (planner) | `sync/plan.ts` | Pure: what to send. Append-only between rebuilds (below). |
|
|
19
|
+
| `StateStore` | `sync/state.ts`, `sync/documents.ts` | Sync state and the compiled document list per worktree and model, in `.git/adaptiqai-code/`. |
|
|
20
|
+
| `MemoryService` | `ncm/client.ts` | Collections over `/v1/memories`; sub-agent questions as chat turns in fresh helper sessions that include the collection. |
|
|
21
|
+
| (sub-agents) | `swarm/` | Roles (explorer, relations, reviewer, planner, tests), parallel fan-out, questions routed to the code they name (`route.ts`: definitions and uses found on disk go with the question), answers grounded in the files on disk. |
|
|
22
|
+
| `CodeApp` | `app.ts` | The facade every surface drives. |
|
|
23
|
+
| surfaces | `mcp/`, `cli/`, `adapters/` | MCP server, CLI, Claude Code / Codex / Cursor / Continue / Pi adapters, git hooks. |
|
|
24
|
+
|
|
25
|
+
The structure tools (`code_find`, `code_relations`, `code_impact`) answer from
|
|
26
|
+
a graph built locally from the working tree: no model call, always current.
|
|
27
|
+
|
|
28
|
+
## How it stays current
|
|
29
|
+
|
|
30
|
+
A compiled memory is a causal chain: a change recompiles everything after it.
|
|
31
|
+
Measured on the Qwen RTX pod (Qwen3.8-Flash-Next, 2026-10-31, 221k-token
|
|
32
|
+
repository):
|
|
33
|
+
|
|
34
|
+
| Change | Ready after |
|
|
35
|
+
| --- | --- |
|
|
36
|
+
| First compile | 74 s |
|
|
37
|
+
| New text only at the end | 6.3 s |
|
|
38
|
+
| An edit in the middle of the chain | 76 s (everything again) |
|
|
39
|
+
| Base and an overlay as two collections | first question 84 s (the set compiled again) |
|
|
40
|
+
| The changed file appended as a newer copy | 11.4 s |
|
|
41
|
+
|
|
42
|
+
So between rebuilds a sync only appends: a changed file is added at the end
|
|
43
|
+
as `<path> (updated n)` with a line saying it replaces every earlier copy, and
|
|
44
|
+
deleted files are listed. The model chose the newer copy where the two
|
|
45
|
+
disagree (6/6, including a conflicting constant). A rebuild compiles the
|
|
46
|
+
repository afresh in the background (the old version serves until the new
|
|
47
|
+
one is ready) when appended text passes 20% of the base, 40 appended
|
|
48
|
+
documents, a branch change or seven days.
|
|
49
|
+
|
|
50
|
+
Hooks: git `post-commit`, `post-merge`, `post-checkout` and `post-rewrite`,
|
|
51
|
+
and the harness's edit events, start one debounced background sync.
|
|
52
|
+
|
|
53
|
+
## Measured end to end (gateway, Qwen RTX)
|
|
54
|
+
|
|
55
|
+
| | Result |
|
|
56
|
+
| --- | --- |
|
|
57
|
+
| `init` on this repository's 133 files (368k tokens) | 144 s |
|
|
58
|
+
| One `code_ask` | 4.1 s |
|
|
59
|
+
| 11 sub-agents at once | 26 s in all |
|
|
60
|
+
| Where-is questions | 11/12 (the miss was a right file name in a wrong folder; grounding now corrects such paths) |
|
|
61
|
+
| `git commit` of two changed files, synced by the hook | 13.9 s, both answered correctly |
|
|
62
|
+
|
|
63
|
+
Pi on the same model, six lookups one search answers:
|
|
64
|
+
|
|
65
|
+
| | Without | With the repository bound to every request |
|
|
66
|
+
| --- | --- | --- |
|
|
67
|
+
| Correct | 6/6 | 6/6 |
|
|
68
|
+
| Time | 32.5 s | 89.9 s |
|
|
69
|
+
| Tool calls | 22 | 18 |
|
|
70
|
+
|
|
71
|
+
Binding the whole repository to every turn of the main agent costs each turn
|
|
72
|
+
the restore of the memory, and the agent still searches. So the default is
|
|
73
|
+
sub-agents on demand: the main agent's turns stay small and it asks the
|
|
74
|
+
repository when a question needs it. Binding to every request is the
|
|
75
|
+
`native` option.
|
|
76
|
+
|
|
77
|
+
With that default, nine tasks (the six lookups and three that need several
|
|
78
|
+
files):
|
|
79
|
+
|
|
80
|
+
| | Without | Sub-agents on demand |
|
|
81
|
+
| --- | --- | --- |
|
|
82
|
+
| Correct | 8/9 | 8/9 |
|
|
83
|
+
| Time | 61.5 s | 61.2 s |
|
|
84
|
+
| Input tokens | 116k | 87k |
|
|
85
|
+
| Tool calls | 36 | 37 |
|
|
86
|
+
|
|
87
|
+
On a repository of 133 files one search usually finds the answer, so the
|
|
88
|
+
gain is small. The case the design is for (large repositories, questions
|
|
89
|
+
that cross many files, many sub-agents at once) is not measured yet.
|
|
90
|
+
|
|
91
|
+
## A team in memory
|
|
92
|
+
|
|
93
|
+
Agents on one repository share what they learn inside AdaptiqAI memory, not
|
|
94
|
+
by pasting text into each other's prompts (`src/team/`).
|
|
95
|
+
|
|
96
|
+
- **Members.** Every member is one session in memory. A member reads the
|
|
97
|
+
others' conversations (the newest, up to the link limit) from when it
|
|
98
|
+
joins, and every agent reads each member that joins after it. A sub-agent
|
|
99
|
+
answers once and never reads again, so no later member is linked into it,
|
|
100
|
+
and one that leaves the team is deleted from memory. A harness whose own
|
|
101
|
+
model runs on AdaptiqAI joins with its own session
|
|
102
|
+
(`adaptiqai-code team join --session <id>`); a harness whose model does not
|
|
103
|
+
(Claude Code) gets a session that stands for it.
|
|
104
|
+
- **Telling the team.** `code_note` is a turn in the agent's own session; the
|
|
105
|
+
others read it from memory seconds later.
|
|
106
|
+
- **Asking.** `code_ask` and `code_fanout` sub-agents read the repository and
|
|
107
|
+
every member's conversation, so they know what any member was told or found.
|
|
108
|
+
- **Fusion.** A planner splits a task. The sub-agents for its parts join the
|
|
109
|
+
team in one round: each reads the conversations the planner read, in the
|
|
110
|
+
same order, so the engine compiles what they read once for all of them,
|
|
111
|
+
and no link changes it during their turns. They answer in parallel, and an
|
|
112
|
+
answer is in its conversation when its turn ends (the engine takes it in
|
|
113
|
+
then, MrRopke/adaptiq-vllm#271). A lead, linked to the asker and the
|
|
114
|
+
sub-agents while they work, asks once they answered; meanwhile the team
|
|
115
|
+
links to the new sub-agents. With depth above 1 a part runs as a fusion of
|
|
116
|
+
its own. The newest 8 sub-agents stay in the team; older ones leave and
|
|
117
|
+
free their links (a session reads at most 16 others).
|
|
118
|
+
|
|
119
|
+
Measured on a Qwen RTX test pod (EUR-IS-1, never on the gateway; the
|
|
120
|
+
production build plus links both ways, MrRopke/adaptiq-vllm#269; the model's
|
|
121
|
+
own settings and a 5,000,000-token context):
|
|
122
|
+
|
|
123
|
+
| | Result |
|
|
124
|
+
| --- | --- |
|
|
125
|
+
| Agent B reads agent A's conversation | correct, 3.7 s |
|
|
126
|
+
| A fact told to A, then asked of B | correct on the first try, 3.4 s after |
|
|
127
|
+
| Five agents, all linked to all, each told one fact, each asked the four others' | 20/20, round 15.6 s (warm) |
|
|
128
|
+
| Through the plugin: a note from one Claude Code session, asked from another | correct, note 3.1 s, answer 7.3 s |
|
|
129
|
+
| Fusion: planner, 4 parallel sub-agents, lead reading them and the team's note | answered, with the note's facts, 6 sessions in 232.8 s |
|
|
130
|
+
|
|
131
|
+
In the real harness: two DeepSeek Harness sessions on the production gateway
|
|
132
|
+
(`adaptiq-qwen3.8-flash-next`, the model's own settings, 2026-11-01), each
|
|
133
|
+
joined by the plugin's SessionStart hook. One was told a short story in its
|
|
134
|
+
chat, and the other was asked right after:
|
|
135
|
+
|
|
136
|
+
| | Facts right | The asked agent's turn |
|
|
137
|
+
| --- | --- | --- |
|
|
138
|
+
| dsh A told, dsh B asked (5 rounds both ways) | 26/26 | 32.3-83.2 s |
|
|
139
|
+
| Four earlier dsh rounds, members joined by hand | 21/21 | 32.7-68.6 s |
|
|
140
|
+
| Claude Code told (it called code_note), dsh A asked | 6/6 | 99.6 s |
|
|
141
|
+
| dsh A told, Claude Code asked (it called code_ask) | 5/5 | 102.6 s |
|
|
142
|
+
|
|
143
|
+
The time goes to the engine: the asked agent's request gets `425
|
|
144
|
+
AdaptiqMemoryNotReady ... (compiling 0/3184 tokens)` while the one new block
|
|
145
|
+
of the linked conversation waits in the compile queue (7-89 s here, with
|
|
146
|
+
other compiles on the same engine), then 2-46 s to the first token. The test
|
|
147
|
+
pod, with nothing else compiling, took 2.6-4 s.
|
|
148
|
+
|
|
149
|
+
Fusion before and after on the production gateway (Qwen RTX,
|
|
150
|
+
`adaptiq-qwen3.8-flash-next`, the model's own settings, 2026-11-01). This
|
|
151
|
+
repository (720k tokens, one collection) and seven fusion tasks with checked
|
|
152
|
+
answers (`scripts/fusion-check.ts`). Each task ran on main and on this design
|
|
153
|
+
back to back on the same engine build, each with its own team. Runs that a
|
|
154
|
+
gateway or engine outage broke are left out (main's compaction):
|
|
155
|
+
|
|
156
|
+
| Task | Main | This design |
|
|
157
|
+
| --- | --- | --- |
|
|
158
|
+
| retry425 | 125 s, wrong | 483 s, right |
|
|
159
|
+
| links | 1,064 s, wrong | 693 s, right |
|
|
160
|
+
| rebuild | 724 s, wrong | 242 s, right |
|
|
161
|
+
| thinking | 809 s, right | 169 s, right |
|
|
162
|
+
| filters | 166 s, wrong | 351 s, wrong |
|
|
163
|
+
| compaction | (outage) | 321 s, wrong |
|
|
164
|
+
| teamfile | 389 s, wrong | 808 s, wrong |
|
|
165
|
+
| Right | 1/6 | 4/7 |
|
|
166
|
+
| Mean, median | 546 s, 556 s | 438 s, 351 s |
|
|
167
|
+
|
|
168
|
+
Where the time went, mean per fusion:
|
|
169
|
+
|
|
170
|
+
| Phase | Main | This design |
|
|
171
|
+
| --- | --- | --- |
|
|
172
|
+
| Sub-agents' longest wait for their set (425) | 16.7 s | 0 s |
|
|
173
|
+
| Seal turns after the parts | 10.1 s | none |
|
|
174
|
+
| Planner's wait for its set | 0 s | 3.8 s |
|
|
175
|
+
| Lead's wait for its set | 7.1 s | 9.0 s |
|
|
176
|
+
| Tokens the model wrote (thinking and answers) | 38.0k | 36.0k |
|
|
177
|
+
| Link requests | 34 | 28 |
|
|
178
|
+
|
|
179
|
+
Most of a fusion is the model thinking: 36-38k tokens at 28-144 tokens/s,
|
|
180
|
+
depending on the engine's load. A lower thinking level for the planner, the
|
|
181
|
+
parts or the lead was faster (82 s against 231 s on one task) but did not
|
|
182
|
+
keep the answers right, so thinking stays as the model ships.
|
|
183
|
+
|
|
184
|
+
What it took: the planner and the lead think as the model ships (with
|
|
185
|
+
thinking off the planner stopped before its JSON when the repository was in
|
|
186
|
+
memory; with its lowest level it split a task into one part and the answer
|
|
187
|
+
missed a fact). The engine compiles what a session reads as one set per
|
|
188
|
+
list of conversations in link order, so the planner and its sub-agents link
|
|
189
|
+
the same conversations in the same order, one at a time, and share one
|
|
190
|
+
compile. A question waits for its first byte up to the plugin's own
|
|
191
|
+
10-minute limit, not Node's 300 s.
|
|
192
|
+
|
|
193
|
+
## Precision: nothing named that is not there
|
|
194
|
+
|
|
195
|
+
An agent acts on the paths and symbols an answer names, so one invented file
|
|
196
|
+
breaks its trust. What keeps an answer to what exists:
|
|
197
|
+
|
|
198
|
+
- **Grounding** (`swarm/ground.ts`, no model call). Every path is checked
|
|
199
|
+
against the working tree, dotfiles (`.npmrc`) and dot-folders included. A
|
|
200
|
+
wrong folder for a file name found once is corrected, except in a sentence
|
|
201
|
+
that says it is not there ("there is no `packages/code/.npmrc`" stays as
|
|
202
|
+
written). A path no file has and no file names (`.adaptiq/code.json` is
|
|
203
|
+
named by the code, so it stands) is marked "(not in the repository)", a
|
|
204
|
+
code symbol the repository never mentions "(not found in the repository)",
|
|
205
|
+
a line past a file's end "(no line N: it has M)". Code blocks are left as
|
|
206
|
+
written.
|
|
207
|
+
- **Prompts** (`swarm/roles.ts`). "This repository has no such file" is a
|
|
208
|
+
complete answer; a path must be one seen as a document name; a linked
|
|
209
|
+
conversation is never a file; no tools, never "I'll search"; the question's
|
|
210
|
+
own answer form goes first.
|
|
211
|
+
- **The file list** (`repo-map.md`, "Every file"). Every compiled file by
|
|
212
|
+
folder, within a third of the map's budget (1.7k tokens for 336 files), so
|
|
213
|
+
a sub-agent that reads only part of the repository still knows what exists.
|
|
214
|
+
Without it, answers denied files that are there.
|
|
215
|
+
- **An empty answer is an error.** The model sometimes answers with a tool
|
|
216
|
+
call it was never offered; the server drops it and returns no text with
|
|
217
|
+
finish "stop" (measured: 5 of 8 tries of one question, 6 of 49 in a run).
|
|
218
|
+
|
|
219
|
+
The precision set (`bench/precision/`, 49 questions with the truth from the
|
|
220
|
+
code, 10 of them traps whose honest answer is "not here") is scored against
|
|
221
|
+
the checkout's files. Measured on the gateway, Qwen RTX installer set
|
|
222
|
+
2d67444d, one collection of the set's 127 files, each answer read by hand as
|
|
223
|
+
well:
|
|
224
|
+
|
|
225
|
+
| | Correct | Wrong | Invented | Unanswered |
|
|
226
|
+
| --- | --- | --- | --- | --- |
|
|
227
|
+
| Before (main d6ee785) | 43 | 2 | 4 | 0 |
|
|
228
|
+
| After | 48 | 0 | 1 | 0 |
|
|
229
|
+
|
|
230
|
+
Before, the inventions were a file (`packages/code/src/sync/sync.ts`), two
|
|
231
|
+
symbols and a claimed `eslint.config.js`; the wrong answers denied files that
|
|
232
|
+
exist (`pnpm-workspace.yaml`, the CI workflows). After, the one miss put the
|
|
233
|
+
root `.npmrc` in `packages/code` in prose, as no path grounding could check.
|
|
234
|
+
On the earlier main (81fc117, thinking off, installer set 332113e2) the same
|
|
235
|
+
set went from 42 correct and 6 unanswered to 49 correct.
|
|
236
|
+
|
|
237
|
+
The `.npmrc` that started this was no invented file: `.npmrc` exists and was
|
|
238
|
+
the first document compiled. The model put a teammate's note, said in a
|
|
239
|
+
linked conversation, in that file ("recorded in `.npmrc`'s conversation",
|
|
240
|
+
"open `.npmrc`, the note itself"). The same probe (`team-probe.ts`, three
|
|
241
|
+
tries) put the note in a workflow file 2 of 3 times on 81fc117; after, 0 of 3,
|
|
242
|
+
and the file the note names is no longer denied (3 of 3 before on d6ee785,
|
|
243
|
+
0 of 3 after).
|
|
244
|
+
|
|
245
|
+
## Known limits
|
|
246
|
+
|
|
247
|
+
- A sub-agent reads a selected working set of a large repository per
|
|
248
|
+
question (130k of 372k tokens here), not all of it at once.
|
|
249
|
+
- Grounding sees a path only when it is written as one: "the `.npmrc` is in
|
|
250
|
+
`packages/code`" names no path to check.
|
|
251
|
+
- An app a person signed in (`adaptiqai-code login`, the dsh sign-in) may
|
|
252
|
+
write at most 64 sources and 8 MB at once, so a larger list goes as packs
|
|
253
|
+
of files of up to 128 KB, in order (an append changes only the last pack).
|
|
254
|
+
A repository past 8 MB of text needs `.adaptiqignore`.
|
|
255
|
+
- In DeepSeek Harness the MCP server starts in the folder dsh started in, so
|
|
256
|
+
the code_* tools serve that repository; the team hooks follow each
|
|
257
|
+
session's own folder.
|
|
258
|
+
- A rebuild costs a full compile; an engine change that adopts the longest
|
|
259
|
+
unchanged prefix at any point (with recurrent snapshots along knowledge
|
|
260
|
+
tapes) would make it cheap.
|
|
261
|
+
- Usage: a seeded collection's prefix was billed as new input (242,200 tokens
|
|
262
|
+
per question); the engine fix counts it as a memory read.
|
package/README.md
CHANGED
|
@@ -1,3 +1,123 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AdaptiqAI Code
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Your whole git repository, compiled into AdaptiqAI's model memory and kept
|
|
4
|
+
current from git. Your coding agent and every sub-agent it starts ask the
|
|
5
|
+
repository instead of grepping and opening files one by one: where something
|
|
6
|
+
is, how parts connect, what a change would break.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install -g @adaptiqai/code
|
|
10
|
+
cd your-repository
|
|
11
|
+
adaptiqai-code init
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`init` compiles the repository (the first time takes a while; later syncs
|
|
15
|
+
only send what changed), turns AdaptiqAI Code on for this repository, sets up
|
|
16
|
+
the coding agents it finds on this computer, and adds the git hooks that keep
|
|
17
|
+
the memory current.
|
|
18
|
+
|
|
19
|
+
AdaptiqAI Code uses this computer's AdaptiqAI sign-in, the same one the
|
|
20
|
+
AdaptiqAI MCP app uses, or `ADAPTIQAI_API_KEY` when it is set.
|
|
21
|
+
`adaptiqai-code login` signs in in the browser.
|
|
22
|
+
|
|
23
|
+
## Your coding agent
|
|
24
|
+
|
|
25
|
+
One command each, run in the repository. `init` already ran the ones for the
|
|
26
|
+
agents it found.
|
|
27
|
+
|
|
28
|
+
| Agent | Command | What it sets up |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| Claude Code | `adaptiqai-code install claude` | Hooks in `.claude/settings.local.json`, the MCP server in `.mcp.json` |
|
|
31
|
+
| Codex CLI | `adaptiqai-code install codex` | Hooks in `~/.codex/hooks.json`, the MCP server in `~/.codex/config.toml` |
|
|
32
|
+
| Cursor | `adaptiqai-code install cursor` | Hooks in `.cursor/hooks.json`, the MCP server in `.cursor/mcp.json` |
|
|
33
|
+
| Continue | `adaptiqai-code install continue` | A rule in `.continue/rules/`, the MCP server in `.continue/mcpServers/` |
|
|
34
|
+
| Pi | `adaptiqai-code install pi` | An extension in `.pi/extensions/` |
|
|
35
|
+
| DeepSeek Harness | `adaptiqai-code install dsh [--profile <name>]` | One block in each profile's `cordis.patch.yml` (the MCP server and the hooks, through dsh's own MCP client and Claude Code hook bridge), the hooks in `~/.dsh/adaptiqai-code/hooks.json` |
|
|
36
|
+
|
|
37
|
+
Claude Code can instead take the package as a plugin (it carries
|
|
38
|
+
`.claude-plugin/plugin.json`, `hooks/hooks.json` and `.mcp.json`); with the
|
|
39
|
+
plugin installed, `install claude` adds nothing, so nothing runs twice. The
|
|
40
|
+
plugin starts `node`, so Node.js 22 or newer has to be on Claude Code's PATH.
|
|
41
|
+
|
|
42
|
+
Your own settings in these files stay as they are: AdaptiqAI Code adds its
|
|
43
|
+
entries beside them and `adaptiqai-code uninstall` takes out only its own.
|
|
44
|
+
Files it creates in the repository are listed in `.git/info/exclude`, so
|
|
45
|
+
they never show up in `git status`.
|
|
46
|
+
|
|
47
|
+
What the agent gets:
|
|
48
|
+
|
|
49
|
+
- **At session start**, a short brief of the repository (what it is, how it
|
|
50
|
+
is laid out, what changed since the last sync).
|
|
51
|
+
- **Tools**: `code_ask` (a sub-agent that has the whole repository in memory
|
|
52
|
+
answers, with `path:line`), `code_fanout` (up to 16 questions at once, in
|
|
53
|
+
parallel), `code_find` (where a symbol is defined, instantly),
|
|
54
|
+
`code_relations` (imports, importers, tests), `code_impact` (what depends on
|
|
55
|
+
a set of files), `code_status` and `code_sync`.
|
|
56
|
+
- **Sub-agents** are told they share the same memory, and are asked as
|
|
57
|
+
helpers of the session that started them.
|
|
58
|
+
|
|
59
|
+
## A team that learns together
|
|
60
|
+
|
|
61
|
+
Every agent on the repository can be in one team in AdaptiqAI memory: each
|
|
62
|
+
reads the others' conversations, so what one learns, the others know seconds
|
|
63
|
+
later.
|
|
64
|
+
|
|
65
|
+
- `code_note` (or `adaptiqai-code note "<title>" "<text>"`): tell the team.
|
|
66
|
+
- `code_fusion` (or `adaptiqai-code fusion "<task>"`): a team of sub-agents
|
|
67
|
+
works on one task in parallel; a lead answers from what they found.
|
|
68
|
+
- `adaptiqai-code team join --session <id> --name <role>`: add an agent whose
|
|
69
|
+
own model runs on AdaptiqAI, with its own conversation.
|
|
70
|
+
- DeepSeek Harness does that by itself: each session on an AdaptiqAI model
|
|
71
|
+
joins the team with its own conversation when it starts, so what one
|
|
72
|
+
session is told, another answers from memory. A session that joins again
|
|
73
|
+
gets back any link a failure left out.
|
|
74
|
+
- `code_team` / `adaptiqai-code team`: who is in the team.
|
|
75
|
+
|
|
76
|
+
## How it stays current
|
|
77
|
+
|
|
78
|
+
- After the agent edits a file, the hook tells the memory which file changed.
|
|
79
|
+
- After a commit, merge, checkout, rebase or amend, the git hooks sync. A hook
|
|
80
|
+
that was already there keeps running first; `uninstall git` puts it back.
|
|
81
|
+
- Syncs run in the background and are debounced: a burst of edits or a long
|
|
82
|
+
rebase becomes one sync.
|
|
83
|
+
- When a session starts with files changed since the last sync, a sync is
|
|
84
|
+
queued first (for at most 3 seconds; it never holds the session up).
|
|
85
|
+
|
|
86
|
+
Hooks never break your agent: if anything goes wrong they print nothing and
|
|
87
|
+
exit 0. `adaptiqai-code doctor` says what is wrong.
|
|
88
|
+
|
|
89
|
+
## Commands
|
|
90
|
+
|
|
91
|
+
| Command | |
|
|
92
|
+
|---|---|
|
|
93
|
+
| `adaptiqai-code init [--harness=claude,codex,...] [--no-git-hooks]` | Compile, turn on, set up agents and git hooks |
|
|
94
|
+
| `adaptiqai-code sync [--full] [--background]` | Sync now (`--full` rebuilds everything) |
|
|
95
|
+
| `adaptiqai-code status` | Where the memory stands: commit, files, tokens, what changed since |
|
|
96
|
+
| `adaptiqai-code ask "<question>" [--role <role>]` | Ask the repository from the terminal |
|
|
97
|
+
| `adaptiqai-code fanout "<question>" "<question>"...` | Several questions at once |
|
|
98
|
+
| `adaptiqai-code find <name>` | Where a symbol is defined |
|
|
99
|
+
| `adaptiqai-code relations <path>` | How a file connects to the rest |
|
|
100
|
+
| `adaptiqai-code impact <path...>` | What depends on these files |
|
|
101
|
+
| `adaptiqai-code brief` | The brief agents get at session start |
|
|
102
|
+
| `adaptiqai-code roles` | The roles a sub-agent can answer in |
|
|
103
|
+
| `adaptiqai-code install <agent...>` / `uninstall [<agent...>]` | Add or take out one agent, or `git` |
|
|
104
|
+
| `adaptiqai-code login` | Sign this computer in to AdaptiqAI |
|
|
105
|
+
| `adaptiqai-code doctor` | Check git, sign-in, model, hooks and the last sync |
|
|
106
|
+
|
|
107
|
+
Most commands take `--json`. `--root <dir>` names another repository.
|
|
108
|
+
`mcp` and `hook <agent> <event>` are what the agents' configs start.
|
|
109
|
+
|
|
110
|
+
## Privacy
|
|
111
|
+
|
|
112
|
+
- Nothing is sent from a repository until you run `init` there. The hooks and
|
|
113
|
+
the MCP server do nothing in any other repository, even when an agent is set
|
|
114
|
+
up for every repository (Codex) or as a plugin (Claude Code).
|
|
115
|
+
`git config adaptiqai-code.enabled` shows whether a repository is on;
|
|
116
|
+
`adaptiqai-code uninstall` turns it off.
|
|
117
|
+
- Files git ignores are never read. Binary files, lockfiles, generated and
|
|
118
|
+
vendored code are left out.
|
|
119
|
+
- A file that holds a credential (a private key, a token, a password
|
|
120
|
+
assignment) is left out whole.
|
|
121
|
+
- To keep more out, list it in `.adaptiqignore` at the repository root, in
|
|
122
|
+
`.gitignore` syntax; a `!` rule there takes a file back in.
|
|
123
|
+
- `adaptiqai-code status` says how many files were left out, and why.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# AdaptiqAI Code as the Claude Code plugin starts it (its MCP server and hooks), through
|
|
3
|
+
# /bin/sh, so a package that lost its file modes still starts (npx runs
|
|
4
|
+
# lib/index.js itself). Claude Code needs no Node.js of its own, and one
|
|
5
|
+
# started from the Dock or a menu often runs without the PATH a terminal gets
|
|
6
|
+
# from nvm, fnm, Volta, asdf, mise or Homebrew, so a Node.js 22 or newer is
|
|
7
|
+
# looked for there too, or ADAPTIQAI_NODE names one. With none, the server
|
|
8
|
+
# still answers, with no tools and instructions that say why: the agent can
|
|
9
|
+
# tell the person, where a server that fails to start says nothing. A hook
|
|
10
|
+
# without Node.js does nothing, so the harness is never held up.
|
|
11
|
+
root=$(cd "$(dirname "$0")/.." && pwd)
|
|
12
|
+
|
|
13
|
+
usable() {
|
|
14
|
+
[ -n "$1" ] && [ -x "$1" ] && "$1" -e 'process.exit(+process.versions.node.split(".")[0] >= 22 ? 0 : 1)' >/dev/null 2>&1
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if [ -n "${ADAPTIQAI_NODE:-}" ]; then
|
|
18
|
+
usable "$ADAPTIQAI_NODE" && exec "$ADAPTIQAI_NODE" "$root/lib/index.js" "$@"
|
|
19
|
+
else
|
|
20
|
+
for node in "$(command -v node 2>/dev/null)" \
|
|
21
|
+
"${VOLTA_HOME:-$HOME/.volta}/bin/node" \
|
|
22
|
+
"${FNM_DIR:-$HOME/.local/share/fnm}/aliases/default/bin/node" \
|
|
23
|
+
"$HOME/Library/Application Support/fnm/aliases/default/bin/node" \
|
|
24
|
+
"$HOME/.asdf/shims/node" "$HOME/.local/share/mise/shims/node" \
|
|
25
|
+
/opt/homebrew/bin/node /usr/local/bin/node /usr/bin/node \
|
|
26
|
+
"${NVM_DIR:-$HOME/.nvm}"/versions/node/*/bin/node; do
|
|
27
|
+
usable "$node" && exec "$node" "$root/lib/index.js" "$@"
|
|
28
|
+
done
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
reason='AdaptiqAI Code is not available here: it needs Node.js 22 or newer on this computer, and the Claude Code plugin found none. When the repository memory would help, tell the person to install Node.js 22 or newer (nodejs.org), or to set ADAPTIQAI_NODE to one in the env of Claude Code'"'"'s settings, and then to start Claude Code again.'
|
|
32
|
+
echo "adaptiqai-code: $reason" >&2
|
|
33
|
+
# Only the MCP server answers; a hook prints nothing and exits.
|
|
34
|
+
[ "${1:-}" = mcp ] || exit 0
|
|
35
|
+
while IFS= read -r line || [ -n "$line" ]; do
|
|
36
|
+
id=$(printf '%s\n' "$line" | sed -nE 's/.*"id":("[^"]*"|-?[0-9]+).*/\1/p')
|
|
37
|
+
# A notification has no id and gets no answer.
|
|
38
|
+
[ -n "$id" ] || continue
|
|
39
|
+
case $line in
|
|
40
|
+
*'"method":"initialize"'*)
|
|
41
|
+
version=$(printf '%s\n' "$line" | sed -nE 's/.*"protocolVersion":"([^"]*)".*/\1/p')
|
|
42
|
+
result="{\"protocolVersion\":\"${version:-2025-06-18}\",\"capabilities\":{\"tools\":{}},\"serverInfo\":{\"name\":\"adaptiqai-code\",\"title\":\"AdaptiqAI Code\",\"version\":\"0.0.0\"},\"instructions\":\"$reason\"}" ;;
|
|
43
|
+
*'"method":"tools/list"'*) result='{"tools":[]}' ;;
|
|
44
|
+
*'"method":"ping"'*) result='{}' ;;
|
|
45
|
+
*)
|
|
46
|
+
printf '{"jsonrpc":"2.0","id":%s,"error":{"code":-32601,"message":"Method not found"}}\n' "$id"
|
|
47
|
+
continue ;;
|
|
48
|
+
esac
|
|
49
|
+
printf '{"jsonrpc":"2.0","id":%s,"result":%s}\n' "$id" "$result"
|
|
50
|
+
done
|
package/hooks/hooks.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "AdaptiqAI Code: the repository's brief at session start, edited files synced into memory, sub-agents told they share it.",
|
|
3
|
+
"hooks": {
|
|
4
|
+
"SessionStart": [
|
|
5
|
+
{
|
|
6
|
+
"matcher": "startup|resume|clear|compact",
|
|
7
|
+
"hooks": [
|
|
8
|
+
{
|
|
9
|
+
"type": "command",
|
|
10
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/bin/adaptiqai-code\" hook claude SessionStart",
|
|
11
|
+
"timeout": 15
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"PostToolUse": [
|
|
17
|
+
{
|
|
18
|
+
"matcher": "Edit|Write|MultiEdit|NotebookEdit|Bash",
|
|
19
|
+
"hooks": [
|
|
20
|
+
{
|
|
21
|
+
"type": "command",
|
|
22
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/bin/adaptiqai-code\" hook claude PostToolUse",
|
|
23
|
+
"async": true,
|
|
24
|
+
"timeout": 30
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"SubagentStart": [
|
|
30
|
+
{
|
|
31
|
+
"hooks": [
|
|
32
|
+
{
|
|
33
|
+
"type": "command",
|
|
34
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/bin/adaptiqai-code\" hook claude SubagentStart",
|
|
35
|
+
"timeout": 10
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
}
|