@poltergeist-ai/cli 0.1.0 → 0.1.6
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/README.md +204 -0
- package/dist/cli.js +494 -46
- package/dist/index.d.ts +36 -0
- package/dist/index.js +494 -46
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# @poltergeist-ai/cli
|
|
2
|
+
|
|
3
|
+
> Build contributor ghost profiles for simulated code reviews.
|
|
4
|
+
|
|
5
|
+
Poltergeist extracts a contributor's review style, coding patterns, and communication voice from git history, GitHub PRs, GitLab MRs, Slack messages, and design docs — then outputs a structured ghost profile that can be used to simulate their code reviews.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @poltergeist-ai/cli extract [options]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or install globally:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g @poltergeist-ai/cli
|
|
17
|
+
poltergeist extract [options]
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Requires Node.js >= 18.17.0.
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
### Basic: build a ghost from a local repo
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx @poltergeist-ai/cli extract \
|
|
28
|
+
--contributor "Alice Smith" \
|
|
29
|
+
--email alice@company.com \
|
|
30
|
+
--git-repo .
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
This mines git history for Alice's commits, coding patterns, and naming conventions. If the repo is hosted on GitHub, PR review comments are fetched automatically.
|
|
34
|
+
|
|
35
|
+
### Full: combine multiple data sources
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npx @poltergeist-ai/cli extract \
|
|
39
|
+
--contributor "Alice Smith" \
|
|
40
|
+
--email alice@company.com \
|
|
41
|
+
--git-repo https://github.com/org/repo \
|
|
42
|
+
--gitlab-export ./exports/gitlab-notes.json \
|
|
43
|
+
--slack-export ./exports/slack/ \
|
|
44
|
+
--docs-dir ./docs/adrs/ \
|
|
45
|
+
--output .poltergeist/ghosts/alice-smith.md
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
More sources produce a more accurate ghost. Review comments (GitHub/GitLab) are the single most valuable input for voice fidelity.
|
|
49
|
+
|
|
50
|
+
### Remote repos
|
|
51
|
+
|
|
52
|
+
Pass a URL to `--git-repo` and the CLI clones it as a bare repo to `.poltergeist/repos/` (automatically added to `.gitignore`). Subsequent runs reuse the cache and fetch updates.
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npx @poltergeist-ai/cli extract \
|
|
56
|
+
--contributor "alice" \
|
|
57
|
+
--git-repo https://github.com/org/repo
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Use the contributor's GitHub username as `--contributor` for best results when extracting from GitHub repos — it matches against PR comment authors.
|
|
61
|
+
|
|
62
|
+
### GitHub rate limits
|
|
63
|
+
|
|
64
|
+
For repos with many PRs, pass a personal access token to avoid rate limiting:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npx @poltergeist-ai/cli extract \
|
|
68
|
+
--contributor "alice" \
|
|
69
|
+
--git-repo https://github.com/org/repo \
|
|
70
|
+
--github-token ghp_xxxxxxxxxxxx
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## CLI reference
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
Usage: poltergeist [extract] [options]
|
|
77
|
+
|
|
78
|
+
Options:
|
|
79
|
+
--contributor <name> Contributor name (required)
|
|
80
|
+
--email <email> Contributor email for git log filtering
|
|
81
|
+
--slug <slug> Output filename slug (default: derived from name)
|
|
82
|
+
--git-repo <path|url> Local repo path or remote URL
|
|
83
|
+
--gitlab-export <path> Path to GitLab MR comments JSON export
|
|
84
|
+
--slack-export <path> Path to Slack export directory
|
|
85
|
+
--docs-dir <path> Path to design docs / ADRs directory
|
|
86
|
+
--github-token <token> GitHub PAT for higher API rate limits
|
|
87
|
+
--output <path> Output path (default: .poltergeist/ghosts/<slug>.md)
|
|
88
|
+
--verbose Enable verbose logging
|
|
89
|
+
--help Show help
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
At least one data source (`--git-repo`, `--gitlab-export`, `--slack-export`, or `--docs-dir`) is required.
|
|
93
|
+
|
|
94
|
+
## Data sources
|
|
95
|
+
|
|
96
|
+
| Source | Flag | What it extracts |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| Git history | `--git-repo` | Coding patterns, naming conventions, commit style, file ownership |
|
|
99
|
+
| GitHub PRs | Auto-detected from `--git-repo` URL | Review voice, severity prefixes, recurring phrases |
|
|
100
|
+
| GitLab MRs | `--gitlab-export` | Review voice, severity prefixes, recurring phrases |
|
|
101
|
+
| Slack | `--slack-export` | Informal technical voice, how they discuss code |
|
|
102
|
+
| Design docs | `--docs-dir` | Architecture reasoning, writing style, decision values |
|
|
103
|
+
|
|
104
|
+
### Exporting GitLab MR comments
|
|
105
|
+
|
|
106
|
+
Use the `glab` CLI to export MR notes:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
glab api "projects/:fullpath/merge_requests?state=merged&per_page=100" \
|
|
110
|
+
| jq -r '.[].iid' \
|
|
111
|
+
| while read IID; do
|
|
112
|
+
glab api "projects/:fullpath/merge_requests/$IID/notes?per_page=100"
|
|
113
|
+
done \
|
|
114
|
+
| jq -s 'add' > gitlab-notes.json
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The expected format is a flat JSON array of note objects with `author.name`, `body`, and `type` fields. The extractor filters by contributor name. See [docs/gitlab-export.md](../../docs/gitlab-export.md) for details.
|
|
118
|
+
|
|
119
|
+
### Exporting Slack messages
|
|
120
|
+
|
|
121
|
+
Use a Slack admin export (or workspace export) and point `--slack-export` at the directory. The extractor scans all channel JSON files for messages matching the contributor name.
|
|
122
|
+
|
|
123
|
+
## Output
|
|
124
|
+
|
|
125
|
+
The CLI generates a ghost file in Markdown with these sections:
|
|
126
|
+
|
|
127
|
+
- **Identity** — name, slug, role, primary domains, sources used
|
|
128
|
+
- **Review philosophy** — ranked values, dealbreakers, what they ignore
|
|
129
|
+
- **Communication style** — tone, severity prefixes, vocabulary, comment length
|
|
130
|
+
- **Code patterns** — patterns they prefer, push back on, and commonly suggest
|
|
131
|
+
- **Known blind spots** — areas they historically under-review
|
|
132
|
+
- **Example review comments** — verbatim excerpts for voice grounding
|
|
133
|
+
|
|
134
|
+
Sections marked `[fill in manually]` need human input. The manual pass is the most important step — especially ranked values and example comments.
|
|
135
|
+
|
|
136
|
+
### After extraction
|
|
137
|
+
|
|
138
|
+
1. Open the ghost file and fill in all `[fill in manually]` sections
|
|
139
|
+
2. Review the sample comments — they are the most important voice signal
|
|
140
|
+
3. Validate with a teammate who knows the contributor
|
|
141
|
+
4. Test with a review: `git diff main | claude "review as @alice-smith"`
|
|
142
|
+
|
|
143
|
+
## Library API
|
|
144
|
+
|
|
145
|
+
The extractors and generator are available as ES module exports for programmatic use:
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
import {
|
|
149
|
+
extractGitSignals,
|
|
150
|
+
summariseGit,
|
|
151
|
+
extractGitHubSignals,
|
|
152
|
+
extractGitLabSignals,
|
|
153
|
+
summariseGitLab,
|
|
154
|
+
extractSlackSignals,
|
|
155
|
+
summariseSlack,
|
|
156
|
+
extractDocsSignals,
|
|
157
|
+
buildGhostMarkdown,
|
|
158
|
+
slugify,
|
|
159
|
+
} from "@poltergeist-ai/cli";
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Each data source follows the same pattern: an `extract*Signals()` function that reads raw data, and a `summarise*()` function that distills it into observations. Pass the observations to `buildGhostMarkdown()` to generate the output.
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
import {
|
|
166
|
+
extractGitSignals,
|
|
167
|
+
summariseGit,
|
|
168
|
+
extractCodeStyleFromDiff,
|
|
169
|
+
summariseCodeStyle,
|
|
170
|
+
buildGhostMarkdown,
|
|
171
|
+
} from "@poltergeist-ai/cli";
|
|
172
|
+
|
|
173
|
+
const gitSignals = extractGitSignals("/path/to/repo", "Alice Smith", "alice@co.com");
|
|
174
|
+
const gitObs = summariseGit(gitSignals);
|
|
175
|
+
|
|
176
|
+
const codeStyleSignals = extractCodeStyleFromDiff(gitSignals.rawDiffOutput ?? "");
|
|
177
|
+
const codeStyleObs = summariseCodeStyle(codeStyleSignals);
|
|
178
|
+
|
|
179
|
+
const markdown = buildGhostMarkdown({
|
|
180
|
+
contributor: "Alice Smith",
|
|
181
|
+
slug: "alice-smith",
|
|
182
|
+
gitObs,
|
|
183
|
+
codeStyleObs,
|
|
184
|
+
reviewObs: {},
|
|
185
|
+
slackObs: {},
|
|
186
|
+
docsSignals: { authoredDocs: [], docExcerpts: [] },
|
|
187
|
+
sourcesUsed: ["git-history"],
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Ethics
|
|
192
|
+
|
|
193
|
+
Ghost profiles simulate a contributor's review style. They are not that contributor. Always:
|
|
194
|
+
|
|
195
|
+
- Get contributor consent before building their ghost
|
|
196
|
+
- Keep ghosts up to date (mark stale after 6 months)
|
|
197
|
+
- Never use ghost reviews as sole merge approval
|
|
198
|
+
- Make simulation explicit (reviews include a footer)
|
|
199
|
+
|
|
200
|
+
See [docs/ethics.md](../../docs/ethics.md) for full guidelines.
|
|
201
|
+
|
|
202
|
+
## License
|
|
203
|
+
|
|
204
|
+
MIT
|