@mukulaggarwal/pacman 0.1.2 → 0.1.4
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 +164 -18
- package/dist/{chunk-VCDPIN57.js → chunk-WH3UMGHQ.js} +21 -16
- package/dist/chunk-WH3UMGHQ.js.map +1 -0
- package/dist/index.js +44 -40
- package/dist/index.js.map +1 -1
- package/dist/mcp-compat.js +3 -3
- package/dist/mcp-compat.js.map +1 -1
- package/dist/onboarding-server.js +529 -46
- package/dist/onboarding-server.js.map +1 -1
- package/dist/onboarding-web/assets/index-BOAOMlJT.css +1 -0
- package/dist/onboarding-web/assets/index-roRRNUhE.js +71 -0
- package/dist/onboarding-web/index.html +10 -3
- package/package.json +1 -1
- package/dist/chunk-VCDPIN57.js.map +0 -1
- package/dist/onboarding-web/assets/index-D60Moe_-.css +0 -1
- package/dist/onboarding-web/assets/index-DkFsbndL.js +0 -75
package/README.md
CHANGED
|
@@ -1,39 +1,185 @@
|
|
|
1
1
|
# pacman
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
```text
|
|
4
|
+
____ _ ____ __ __ _ _ _
|
|
5
|
+
| _ \ / \ / ___| \/ | / \ | \ | |
|
|
6
|
+
| |_) / _ \| | | |\/| | / _ \ | \| |
|
|
7
|
+
| __/ ___ \ |___| | | |/ ___ \| |\ |
|
|
8
|
+
|_| /_/ \_\____|_| |_/_/ \_\_| \_|
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
> Waka through project context with Claude Code, Codex, and Slack.
|
|
12
|
+
> Your memory stays in local files or a Google Drive folder you control.
|
|
13
|
+
|
|
14
|
+
## Arcade Pitch
|
|
15
|
+
|
|
16
|
+
Use `pacman` when you want assistants to stay grounded in your actual workspace instead of a hidden hosted database.
|
|
17
|
+
|
|
18
|
+
- Keep context in Markdown and JSON you can inspect
|
|
19
|
+
- Share one workspace across Claude Code, Codex, and Slack
|
|
20
|
+
- Register one MCP server for both coding clients
|
|
21
|
+
- Sync project signals from tools like Slack, GitHub, GitLab, Gmail, and Google Drive
|
|
22
|
+
- Generate replies from saved canonical context, derived summaries, and raw evidence you control
|
|
4
23
|
|
|
5
|
-
|
|
24
|
+
## Insert Coin
|
|
6
25
|
|
|
7
26
|
```bash
|
|
8
27
|
npm install -g @mukulaggarwal/pacman
|
|
9
28
|
```
|
|
10
29
|
|
|
11
|
-
|
|
30
|
+
<details>
|
|
31
|
+
<summary><strong>Check that the cabinet booted</strong></summary>
|
|
12
32
|
|
|
13
33
|
```bash
|
|
14
|
-
pacman
|
|
15
|
-
pacman claude install
|
|
16
|
-
pacman codex install
|
|
17
|
-
pacman mcp claude install
|
|
18
|
-
pacman mcp codex install
|
|
19
|
-
pacman daemon
|
|
20
|
-
pacman slack listen
|
|
34
|
+
pacman --help
|
|
35
|
+
pacman mcp claude install --help
|
|
36
|
+
pacman mcp codex install --help
|
|
21
37
|
```
|
|
22
38
|
|
|
23
|
-
|
|
39
|
+
</details>
|
|
40
|
+
|
|
41
|
+
<details>
|
|
42
|
+
<summary><strong>Upgrade to the latest build</strong></summary>
|
|
24
43
|
|
|
25
44
|
```bash
|
|
26
|
-
|
|
27
|
-
personal-assistant-mcp
|
|
45
|
+
npm install -g @mukulaggarwal/pacman@latest
|
|
28
46
|
```
|
|
29
47
|
|
|
30
|
-
|
|
48
|
+
</details>
|
|
49
|
+
|
|
50
|
+
## Choose Your Route
|
|
51
|
+
|
|
52
|
+
<details open>
|
|
53
|
+
<summary><strong>Level 1: Spawn your workspace</strong></summary>
|
|
31
54
|
|
|
32
55
|
```bash
|
|
33
|
-
|
|
34
|
-
codex mcp add personal_assistant --env PA_WORKSPACE=$HOME/.personal-assistant -- npx -y pacman mcp serve
|
|
56
|
+
pacman init -d .personal-assistant
|
|
35
57
|
```
|
|
36
58
|
|
|
37
|
-
|
|
59
|
+
This launches the onboarding UI and configures your profile, assistant identity, storage backend, integrations, and sync schedule.
|
|
60
|
+
|
|
61
|
+
</details>
|
|
62
|
+
|
|
63
|
+
<details open>
|
|
64
|
+
<summary><strong>Level 2: Equip Claude Code and Codex</strong></summary>
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pacman claude install -d . -w .personal-assistant
|
|
68
|
+
pacman codex install -d . -w .personal-assistant
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
This writes:
|
|
72
|
+
|
|
73
|
+
- `CLAUDE.md` for Claude Code
|
|
74
|
+
- `AGENTS.md` for Codex
|
|
75
|
+
- shared Pac-Man skills under `~/.claude/skills/` and `~/.codex/skills/`
|
|
76
|
+
|
|
77
|
+
</details>
|
|
78
|
+
|
|
79
|
+
<details open>
|
|
80
|
+
<summary><strong>Level 3: Power up MCP</strong></summary>
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
pacman mcp claude install -w .personal-assistant
|
|
84
|
+
pacman mcp codex install -w .personal-assistant
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Restart Claude Code or Codex after MCP registration.
|
|
88
|
+
|
|
89
|
+
</details>
|
|
90
|
+
|
|
91
|
+
<details>
|
|
92
|
+
<summary><strong>Secret tunnel: Manual MCP fallback</strong></summary>
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
claude mcp add -s user --env=PA_WORKSPACE=$HOME/.personal-assistant pacman -- npx -y pacman mcp serve
|
|
96
|
+
codex mcp add pacman --env PA_WORKSPACE=$HOME/.personal-assistant -- npx -y pacman mcp serve
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
</details>
|
|
100
|
+
|
|
101
|
+
<details>
|
|
102
|
+
<summary><strong>Level 4: Keep the map fresh</strong></summary>
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
pacman daemon -d .personal-assistant
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Run the background sync to ingest enabled integrations and rebuild indexes.
|
|
109
|
+
|
|
110
|
+
</details>
|
|
111
|
+
|
|
112
|
+
<details>
|
|
113
|
+
<summary><strong>Level 5: Turn on Slack mode</strong></summary>
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
pacman slack listen -d .personal-assistant
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Use this when you want Slack replies grounded in saved project context.
|
|
120
|
+
|
|
121
|
+
</details>
|
|
122
|
+
|
|
123
|
+
## Game Modes
|
|
124
|
+
|
|
125
|
+
| Mode | What it unlocks |
|
|
126
|
+
| --- | --- |
|
|
127
|
+
| `pacman init` | Launch onboarding and create the workspace |
|
|
128
|
+
| `pacman claude install` | Add Claude Code project guidance |
|
|
129
|
+
| `pacman codex install` | Add Codex project guidance |
|
|
130
|
+
| `pacman mcp claude install` | Register the MCP server with Claude Code |
|
|
131
|
+
| `pacman mcp codex install` | Register the MCP server with Codex |
|
|
132
|
+
| `pacman daemon` | Run scheduled sync and indexing |
|
|
133
|
+
| `pacman slack listen` | Start Slack auto-reply handling |
|
|
134
|
+
|
|
135
|
+
## Player Guide
|
|
136
|
+
|
|
137
|
+
<details>
|
|
138
|
+
<summary><strong>Claude Code lane</strong></summary>
|
|
139
|
+
|
|
140
|
+
After install:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
pacman claude install -d . -w .personal-assistant
|
|
144
|
+
pacman mcp claude install -w .personal-assistant
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Then restart Claude Code and use Pac-Man guidance plus MCP-backed context reads and updates.
|
|
148
|
+
|
|
149
|
+
</details>
|
|
150
|
+
|
|
151
|
+
<details>
|
|
152
|
+
<summary><strong>Codex lane</strong></summary>
|
|
153
|
+
|
|
154
|
+
After install:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
pacman codex install -d . -w .personal-assistant
|
|
158
|
+
pacman mcp codex install -w .personal-assistant
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Then restart Codex and ask it to load, search, read, or update project context through Pac-Man MCP tools.
|
|
162
|
+
|
|
163
|
+
</details>
|
|
164
|
+
|
|
165
|
+
<details>
|
|
166
|
+
<summary><strong>Slack lane</strong></summary>
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
pacman slack listen -d .personal-assistant
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Slack replies are additive. They use the same saved workspace and do not replace MCP-based context access in Claude Code or Codex.
|
|
173
|
+
|
|
174
|
+
</details>
|
|
175
|
+
|
|
176
|
+
## High Score Traits
|
|
177
|
+
|
|
178
|
+
- Privacy first: no mandatory hosted project database
|
|
179
|
+
- Inspectable storage: Markdown and JSON live in your workspace
|
|
180
|
+
- Shared memory: Claude Code, Codex, and Slack use the same context base
|
|
181
|
+
- Grounded retrieval: canonical context, derived summaries, and raw evidence stay connected
|
|
182
|
+
|
|
183
|
+
## Full Map
|
|
38
184
|
|
|
39
|
-
- https://github.com/mukulaggarwal/personal-assistant-with-context
|
|
185
|
+
- Repository and full docs: https://github.com/mukulaggarwal/personal-assistant-with-context
|
|
@@ -21,7 +21,8 @@ import * as path from "path";
|
|
|
21
21
|
import { execFile } from "child_process";
|
|
22
22
|
import { promisify } from "util";
|
|
23
23
|
var execFileAsync = promisify(execFile);
|
|
24
|
-
var MCP_SERVER_NAME = "
|
|
24
|
+
var MCP_SERVER_NAME = "pacman";
|
|
25
|
+
var LEGACY_MCP_SERVER_NAMES = ["personal_assistant"];
|
|
25
26
|
var DEFAULT_WORKSPACE = path.join(os.homedir(), ".personal-assistant");
|
|
26
27
|
async function runCommand(command, args) {
|
|
27
28
|
const result = await execFileAsync(command, args);
|
|
@@ -56,12 +57,14 @@ async function installClaudeMcp(workspacePath, resolveCommand = resolvePacmanSer
|
|
|
56
57
|
const serverCommand = await resolveCommand();
|
|
57
58
|
const fallbackCommand = formatClaudeManualInstallCommand(workspacePath, serverCommand);
|
|
58
59
|
try {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
for (const serverName of [MCP_SERVER_NAME, ...LEGACY_MCP_SERVER_NAMES]) {
|
|
61
|
+
try {
|
|
62
|
+
await runner("claude", ["mcp", "remove", "-s", "user", serverName]);
|
|
63
|
+
} catch (err) {
|
|
64
|
+
const code = typeof err === "object" && err !== null && "code" in err ? String(err.code) : "";
|
|
65
|
+
if (code === "ENOENT") {
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
65
68
|
}
|
|
66
69
|
}
|
|
67
70
|
await runner("claude", [
|
|
@@ -121,8 +124,10 @@ async function installCodexMcp(workspacePath, resolveCommand = resolvePacmanServ
|
|
|
121
124
|
try {
|
|
122
125
|
const { stdout } = await runner("codex", ["mcp", "list", "--json"]);
|
|
123
126
|
const servers = parseCodexServerList(stdout);
|
|
124
|
-
|
|
125
|
-
|
|
127
|
+
for (const serverName of [MCP_SERVER_NAME, ...LEGACY_MCP_SERVER_NAMES]) {
|
|
128
|
+
if (servers.some((server) => server.name === serverName)) {
|
|
129
|
+
await runner("codex", ["mcp", "remove", serverName]);
|
|
130
|
+
}
|
|
126
131
|
}
|
|
127
132
|
await runner("codex", [
|
|
128
133
|
"mcp",
|
|
@@ -155,7 +160,7 @@ function normalizeCodexInstallError(err, fallbackCommand) {
|
|
|
155
160
|
}
|
|
156
161
|
const details = stderr.trim() || message;
|
|
157
162
|
return new Error(
|
|
158
|
-
`Unable to register the
|
|
163
|
+
`Unable to register the Pac-Man MCP server with Codex. ${details} Manual fallback: \`${fallbackCommand}\``
|
|
159
164
|
);
|
|
160
165
|
}
|
|
161
166
|
function normalizeClaudeInstallError(err, fallbackCommand) {
|
|
@@ -169,7 +174,7 @@ function normalizeClaudeInstallError(err, fallbackCommand) {
|
|
|
169
174
|
}
|
|
170
175
|
const details = stderr.trim() || message;
|
|
171
176
|
return new Error(
|
|
172
|
-
`Unable to register the
|
|
177
|
+
`Unable to register the Pac-Man MCP server with Claude Code. ${details} Manual fallback: \`${fallbackCommand}\``
|
|
173
178
|
);
|
|
174
179
|
}
|
|
175
180
|
|
|
@@ -207,7 +212,7 @@ async function startMcpServer(workspacePath) {
|
|
|
207
212
|
alerts: []
|
|
208
213
|
};
|
|
209
214
|
const server = new McpServer({
|
|
210
|
-
name: "
|
|
215
|
+
name: "pacman",
|
|
211
216
|
version: "0.1.0"
|
|
212
217
|
});
|
|
213
218
|
function textResult(text, isError = false) {
|
|
@@ -256,7 +261,7 @@ ${steps.map((step, index) => `${index + 1}. ${step}`).join("\n")}`;
|
|
|
256
261
|
}
|
|
257
262
|
function storageUnavailableMessage() {
|
|
258
263
|
const sections = [
|
|
259
|
-
`
|
|
264
|
+
`Pac-Man MCP storage is unavailable: ${runtimeHealth.storage.reason ?? runtimeHealth.storage.summary}`,
|
|
260
265
|
formatSteps("Fix", runtimeHealth.storage.fix),
|
|
261
266
|
formatSteps("Restart", runtimeHealth.storage.restart)
|
|
262
267
|
].filter(Boolean);
|
|
@@ -264,10 +269,10 @@ ${steps.map((step, index) => `${index + 1}. ${step}`).join("\n")}`;
|
|
|
264
269
|
}
|
|
265
270
|
function logStartupHealth() {
|
|
266
271
|
if (runtimeHealth.alerts.length === 0) {
|
|
267
|
-
console.error(`
|
|
272
|
+
console.error(`Pac-Man MCP ready. Storage: ${runtimeHealth.storage.mode}`);
|
|
268
273
|
return;
|
|
269
274
|
}
|
|
270
|
-
console.error("
|
|
275
|
+
console.error("Pac-Man MCP startup alerts:");
|
|
271
276
|
for (const alert of runtimeHealth.alerts) {
|
|
272
277
|
console.error(`- ${alert.component} ${alert.name}: ${alert.reason}`);
|
|
273
278
|
for (const step of alert.fix) {
|
|
@@ -804,4 +809,4 @@ export {
|
|
|
804
809
|
installCodexMcp,
|
|
805
810
|
startMcpServer
|
|
806
811
|
};
|
|
807
|
-
//# sourceMappingURL=chunk-
|
|
812
|
+
//# sourceMappingURL=chunk-WH3UMGHQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp-installers.ts","../src/mcp-server.ts"],"sourcesContent":["import * as fs from 'node:fs/promises';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execFileAsync = promisify(execFile);\n\nexport const MCP_SERVER_NAME = 'pacman';\nexport const LEGACY_MCP_SERVER_NAMES = ['personal_assistant'] as const;\nexport const DEFAULT_WORKSPACE = path.join(os.homedir(), '.personal-assistant');\n\nexport interface ServerCommand {\n command: string;\n args: string[];\n}\n\nexport interface CommandResult {\n stdout: string;\n stderr: string;\n}\n\nexport interface CodexMcpServer {\n name: string;\n}\n\nexport type CommandRunner = (\n command: string,\n args: string[],\n) => Promise<CommandResult>;\n\nasync function runCommand(command: string, args: string[]): Promise<CommandResult> {\n const result = await execFileAsync(command, args);\n return {\n stdout: result.stdout ?? '',\n stderr: result.stderr ?? '',\n };\n}\n\nexport async function resolveWorkspacePath(dirOpt?: string): Promise<string> {\n if (dirOpt) {\n return path.resolve(dirOpt);\n }\n\n const rcPath = path.join(os.homedir(), '.personal-assistant-rc.json');\n try {\n const rc = JSON.parse(await fs.readFile(rcPath, 'utf-8')) as { workspacePath?: string };\n if (rc.workspacePath) {\n return rc.workspacePath;\n }\n } catch {\n // Fall back to the default workspace.\n }\n\n return DEFAULT_WORKSPACE;\n}\n\nexport async function resolvePacmanServerCommand(): Promise<ServerCommand> {\n const scriptPath = path.resolve(process.argv[1]);\n return { command: process.execPath, args: [scriptPath, 'mcp', 'serve'] };\n}\n\nexport async function resolveCompatServerCommand(): Promise<ServerCommand> {\n const scriptPath = path.resolve(process.argv[1]);\n return { command: process.execPath, args: [scriptPath] };\n}\n\nexport async function installClaudeMcp(\n workspacePath: string,\n resolveCommand: () => Promise<ServerCommand> = resolvePacmanServerCommand,\n runner: CommandRunner = runCommand,\n): Promise<void> {\n const serverCommand = await resolveCommand();\n const fallbackCommand = formatClaudeManualInstallCommand(workspacePath, serverCommand);\n\n try {\n for (const serverName of [MCP_SERVER_NAME, ...LEGACY_MCP_SERVER_NAMES]) {\n try {\n await runner('claude', ['mcp', 'remove', '-s', 'user', serverName]);\n } catch (err) {\n const code = typeof err === 'object' && err !== null && 'code' in err\n ? String((err as { code?: unknown }).code)\n : '';\n if (code === 'ENOENT') {\n throw err;\n }\n }\n }\n\n await runner('claude', [\n 'mcp',\n 'add',\n '-s',\n 'user',\n `--env=PA_WORKSPACE=${workspacePath}`,\n MCP_SERVER_NAME,\n '--',\n serverCommand.command,\n ...serverCommand.args,\n ]);\n } catch (err) {\n throw normalizeClaudeInstallError(err, fallbackCommand);\n }\n}\n\nexport function formatClaudeManualInstallCommand(\n workspacePath: string,\n serverCommand: ServerCommand,\n): string {\n return [\n 'claude',\n 'mcp',\n 'add',\n '-s',\n 'user',\n `--env=${shellQuote(`PA_WORKSPACE=${workspacePath}`)}`,\n MCP_SERVER_NAME,\n '--',\n shellQuote(serverCommand.command),\n ...serverCommand.args.map(shellQuote),\n ].join(' ');\n}\n\nexport function formatCodexManualInstallCommand(\n workspacePath: string,\n serverCommand: ServerCommand,\n): string {\n return [\n 'codex',\n 'mcp',\n 'add',\n MCP_SERVER_NAME,\n '--env',\n shellQuote(`PA_WORKSPACE=${workspacePath}`),\n '--',\n shellQuote(serverCommand.command),\n ...serverCommand.args.map(shellQuote),\n ].join(' ');\n}\n\nexport function parseCodexServerList(stdout: string): CodexMcpServer[] {\n const trimmed = stdout.trim();\n if (trimmed.length === 0) {\n return [];\n }\n\n const jsonStart = trimmed.indexOf('[');\n const json = jsonStart >= 0 ? trimmed.slice(jsonStart) : trimmed;\n return JSON.parse(json) as CodexMcpServer[];\n}\n\nexport async function installCodexMcp(\n workspacePath: string,\n resolveCommand: () => Promise<ServerCommand> = resolvePacmanServerCommand,\n runner: CommandRunner = runCommand,\n): Promise<void> {\n const serverCommand = await resolveCommand();\n const fallbackCommand = formatCodexManualInstallCommand(workspacePath, serverCommand);\n\n try {\n const { stdout } = await runner('codex', ['mcp', 'list', '--json']);\n const servers = parseCodexServerList(stdout);\n\n for (const serverName of [MCP_SERVER_NAME, ...LEGACY_MCP_SERVER_NAMES]) {\n if (servers.some((server) => server.name === serverName)) {\n await runner('codex', ['mcp', 'remove', serverName]);\n }\n }\n\n await runner('codex', [\n 'mcp',\n 'add',\n MCP_SERVER_NAME,\n '--env',\n `PA_WORKSPACE=${workspacePath}`,\n '--',\n serverCommand.command,\n ...serverCommand.args,\n ]);\n } catch (err) {\n throw normalizeCodexInstallError(err, fallbackCommand);\n }\n}\n\nfunction shellQuote(value: string): string {\n if (/^[A-Za-z0-9_./:=+-]+$/.test(value)) {\n return value;\n }\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\nfunction normalizeCodexInstallError(err: unknown, fallbackCommand: string): Error {\n const code = typeof err === 'object' && err !== null && 'code' in err\n ? String((err as { code?: unknown }).code)\n : '';\n const stderr = typeof err === 'object' && err !== null && 'stderr' in err\n ? String((err as { stderr?: unknown }).stderr ?? '')\n : '';\n const message = err instanceof Error ? err.message : String(err);\n\n if (code === 'ENOENT') {\n return new Error(\n `Codex CLI was not found on PATH. Install Codex, then rerun \\`pacman mcp codex install\\`. Manual registration once Codex is available: \\`${fallbackCommand}\\``,\n );\n }\n\n const details = stderr.trim() || message;\n return new Error(\n `Unable to register the Pac-Man MCP server with Codex. ${details} Manual fallback: \\`${fallbackCommand}\\``,\n );\n}\n\nfunction normalizeClaudeInstallError(err: unknown, fallbackCommand: string): Error {\n const code = typeof err === 'object' && err !== null && 'code' in err\n ? String((err as { code?: unknown }).code)\n : '';\n const stderr = typeof err === 'object' && err !== null && 'stderr' in err\n ? String((err as { stderr?: unknown }).stderr ?? '')\n : '';\n const message = err instanceof Error ? err.message : String(err);\n\n if (code === 'ENOENT') {\n return new Error(\n `Claude Code CLI was not found on PATH. Install Claude Code, then rerun \\`pacman mcp claude install\\`. Manual registration once Claude Code is available: \\`${fallbackCommand}\\``,\n );\n }\n\n const details = stderr.trim() || message;\n return new Error(\n `Unable to register the Pac-Man MCP server with Claude Code. ${details} Manual fallback: \\`${fallbackCommand}\\``,\n );\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { createLocalStorage } from '@personal-assistant/storage-local';\nimport { createGDriveStorage } from '@personal-assistant/storage-gdrive';\nimport { createConfigManager } from '@personal-assistant/config-manager';\nimport { createContextManager } from '@personal-assistant/context-manager';\nimport { createIndexer } from '@personal-assistant/indexer';\nimport { createNoopEventClient } from '@personal-assistant/event-client';\nimport { validateIntegrationConfig } from '@personal-assistant/integration-runtime';\nimport type {\n AppConfig,\n GDriveStorageConfig,\n IntegrationConfig,\n StorageBackend,\n} from '@personal-assistant/core-types';\n\ntype ToolResult = {\n content: Array<{ type: 'text'; text: string }>;\n isError?: boolean;\n};\n\ntype HealthStatus = 'healthy' | 'error';\n\ninterface StorageHealth {\n status: HealthStatus;\n mode: 'local' | 'gdrive';\n summary: string;\n reason?: string;\n fix: string[];\n restart: string[];\n}\n\ninterface IntegrationHealth {\n type: IntegrationConfig['type'];\n status: HealthStatus;\n summary: string;\n reason?: string;\n fix: string[];\n restart: string[];\n}\n\ninterface StartupAlert {\n component: 'storage' | 'integration';\n name: string;\n reason: string;\n fix: string[];\n restart: string[];\n}\n\nconst DEFAULT_RESTART_STEPS = [\n 'Restart your MCP client after the configuration has been updated.',\n 'If the registered workspace path changed, rerun `pacman mcp claude install` for Claude Code or `pacman mcp codex install` for Codex before restarting.',\n];\n\nexport async function startMcpServer(workspacePath: string): Promise<void> {\n const localStore = createLocalStorage(workspacePath);\n let storage: StorageBackend = localStore;\n let configManager = createConfigManager(localStore);\n let contextManager = createContextManager(localStore);\n let indexer = createIndexer(localStore);\n const eventClient = createNoopEventClient();\n\n let bootstrapConfig: AppConfig | null = null;\n let storageReadyResolve: (() => void) | undefined;\n const storageReady = new Promise<void>((resolve) => {\n storageReadyResolve = resolve;\n });\n\n const runtimeHealth: {\n storage: StorageHealth;\n integrations: IntegrationHealth[];\n alerts: StartupAlert[];\n } = {\n storage: {\n status: 'healthy',\n mode: 'local',\n summary: `Using local workspace at ${workspacePath}`,\n fix: [],\n restart: DEFAULT_RESTART_STEPS,\n },\n integrations: [],\n alerts: [],\n };\n\n const server = new McpServer({\n name: 'pacman',\n version: '0.1.0',\n });\n\n function textResult(text: string, isError = false): ToolResult {\n return {\n content: [{ type: 'text', text }],\n ...(isError ? { isError: true } : {}),\n };\n }\n\n function getStatusConfig(): AppConfig {\n return bootstrapConfig ?? {\n user: { name: '', assistantName: 'Jarvis', profileType: 'software-engineer', responsibilities: [] },\n storage: { mode: 'local', workspacePath },\n integrations: [],\n sync: {\n dailySyncTime: '09:00',\n timezone: 'UTC',\n manualSyncEnabled: false,\n asyncUpdateEnabled: false,\n },\n };\n }\n\n function addAlert(alert: StartupAlert): void {\n runtimeHealth.alerts.push(alert);\n }\n\n function setStorageFailure(\n mode: 'local' | 'gdrive',\n reason: string,\n fix: string[],\n ): void {\n runtimeHealth.storage = {\n status: 'error',\n mode,\n summary: `Unable to use ${mode} storage`,\n reason,\n fix,\n restart: DEFAULT_RESTART_STEPS,\n };\n addAlert({\n component: 'storage',\n name: mode,\n reason,\n fix,\n restart: DEFAULT_RESTART_STEPS,\n });\n }\n\n function formatSteps(label: string, steps: string[]): string {\n if (steps.length === 0) return '';\n return `${label}:\\n${steps.map((step, index) => `${index + 1}. ${step}`).join('\\n')}`;\n }\n\n function storageUnavailableMessage(): string {\n const sections = [\n `Pac-Man MCP storage is unavailable: ${runtimeHealth.storage.reason ?? runtimeHealth.storage.summary}`,\n formatSteps('Fix', runtimeHealth.storage.fix),\n formatSteps('Restart', runtimeHealth.storage.restart),\n ].filter(Boolean);\n\n return sections.join('\\n\\n');\n }\n\n function logStartupHealth(): void {\n if (runtimeHealth.alerts.length === 0) {\n console.error(`Pac-Man MCP ready. Storage: ${runtimeHealth.storage.mode}`);\n return;\n }\n\n console.error('Pac-Man MCP startup alerts:');\n for (const alert of runtimeHealth.alerts) {\n console.error(`- ${alert.component} ${alert.name}: ${alert.reason}`);\n for (const step of alert.fix) {\n console.error(` Fix: ${step}`);\n }\n for (const step of alert.restart) {\n console.error(` Restart: ${step}`);\n }\n }\n }\n\n function getStorageFixSteps(mode: 'local' | 'gdrive', config?: GDriveStorageConfig): string[] {\n if (mode === 'gdrive') {\n return [\n 'Verify the Google Drive folder ID and OAuth credentials in profile/storage.json.',\n 'If the refresh token is no longer valid, reconnect Google Drive and save the updated configuration.',\n ...(config?.cachePath ? [`Ensure the local cache path exists and is writable: ${config.cachePath}`] : []),\n ];\n }\n\n return [\n `Verify that PA_WORKSPACE points to the correct workspace directory: ${workspacePath}`,\n 'Ensure the workspace directory exists and is writable.',\n 'Run `pacman init` if the workspace has not been initialized yet.',\n ];\n }\n\n function getIntegrationHealth(type: IntegrationConfig['type']): IntegrationHealth | undefined {\n return runtimeHealth.integrations.find((integration) => integration.type === type);\n }\n\n async function ensureStorageAvailable(): Promise<ToolResult | null> {\n await storageReady;\n if (runtimeHealth.storage.status === 'error') {\n return textResult(storageUnavailableMessage(), true);\n }\n return null;\n }\n\n async function resolveStorageBackend(): Promise<void> {\n bootstrapConfig = await configManager.loadConfig();\n runtimeHealth.storage.mode = bootstrapConfig.storage.mode;\n\n if (bootstrapConfig.storage.mode === 'gdrive') {\n const gdriveConfig = bootstrapConfig.storage as GDriveStorageConfig;\n const resolvedCachePath = path.isAbsolute(gdriveConfig.cachePath)\n ? gdriveConfig.cachePath\n : path.resolve(path.dirname(workspacePath), gdriveConfig.cachePath);\n\n try {\n const gdriveStorage = createGDriveStorage({\n ...gdriveConfig,\n cachePath: resolvedCachePath,\n });\n await gdriveStorage.initialize();\n\n storage = gdriveStorage;\n configManager = createConfigManager(gdriveStorage);\n contextManager = createContextManager(gdriveStorage);\n indexer = createIndexer(gdriveStorage);\n bootstrapConfig = await configManager.loadConfig();\n\n runtimeHealth.storage = {\n status: 'healthy',\n mode: 'gdrive',\n summary: `Connected to Google Drive storage${gdriveConfig.folderName ? ` (${gdriveConfig.folderName})` : ''}`,\n fix: [],\n restart: DEFAULT_RESTART_STEPS,\n };\n } catch (err) {\n setStorageFailure(\n 'gdrive',\n err instanceof Error ? err.message : String(err),\n getStorageFixSteps('gdrive', {\n ...gdriveConfig,\n cachePath: resolvedCachePath,\n }),\n );\n }\n } else {\n try {\n await fs.mkdir(workspacePath, { recursive: true });\n runtimeHealth.storage = {\n status: 'healthy',\n mode: 'local',\n summary: `Using local workspace at ${workspacePath}`,\n fix: [],\n restart: DEFAULT_RESTART_STEPS,\n };\n } catch (err) {\n setStorageFailure(\n 'local',\n err instanceof Error ? err.message : String(err),\n getStorageFixSteps('local'),\n );\n }\n }\n\n const configForIntegrations = getStatusConfig();\n runtimeHealth.integrations = [];\n for (const integration of configForIntegrations.integrations.filter((item) => item.enabled)) {\n const result = await validateIntegrationConfig(integration);\n\n if (result.ok) {\n runtimeHealth.integrations.push({\n type: integration.type,\n status: 'healthy',\n summary: result.summary ?? `Connected to ${integration.type}`,\n fix: [],\n restart: DEFAULT_RESTART_STEPS,\n });\n continue;\n }\n\n runtimeHealth.integrations.push({\n type: integration.type,\n status: 'error',\n summary: `Unable to connect to ${integration.type}`,\n reason: result.reason ?? `Unable to connect to ${integration.type}`,\n fix: result.fix ?? [],\n restart: DEFAULT_RESTART_STEPS,\n });\n addAlert({\n component: 'integration',\n name: integration.type,\n reason: result.reason ?? `Unable to connect to ${integration.type}`,\n fix: result.fix ?? [],\n restart: DEFAULT_RESTART_STEPS,\n });\n }\n\n logStartupHealth();\n }\n\n server.tool('config_get', 'Get the full application configuration', {}, async () => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n const config = await configManager.loadConfig();\n return textResult(JSON.stringify(config, null, 2));\n } catch (err) {\n return textResult(`Error loading config: ${err}`, true);\n }\n });\n\n server.tool('config_get_storage_mode', 'Get the current storage mode (local or gdrive)', {}, async () => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n const mode = await configManager.getStorageMode();\n return textResult(mode);\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n });\n\n server.tool('config_get_active_project', 'Get the currently active project name', {}, async () => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n const project = await configManager.getActiveProject();\n return textResult(project ?? 'No active project set');\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n });\n\n server.tool(\n 'config_set_active_project',\n 'Set the active project',\n { project_name: z.string().describe('The project name to set as active') },\n async ({ project_name }) => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n await configManager.setActiveProject(project_name);\n await eventClient.emitWithProject('project_selected', project_name);\n return textResult(`Active project set to: ${project_name}`);\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n },\n );\n\n server.tool('project_list', 'List all known projects', {}, async () => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n const projects = await contextManager.listProjects();\n return textResult(projects.length > 0 ? projects.join('\\n') : 'No projects found');\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n });\n\n server.tool(\n 'project_suggest',\n 'Suggest a project based on context',\n {\n hint: z.string().optional().describe('Optional hint to narrow project suggestion'),\n },\n async ({ hint }) => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n const suggestion = await contextManager.suggestProject(hint);\n if (!suggestion) {\n return textResult('No projects found to suggest');\n }\n return textResult(JSON.stringify(suggestion, null, 2));\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n },\n );\n\n server.tool(\n 'project_get_context',\n 'Get the full context for a project',\n { project_name: z.string().describe('The project name') },\n async ({ project_name }) => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n const context = await contextManager.getProjectContext(project_name);\n await eventClient.emit('mcp_query_executed', { tool: 'project_get_context' });\n\n const parts: string[] = [];\n parts.push(`# Project: ${context.name}\\n`);\n\n for (const file of context.canonicalFiles) {\n parts.push(`## ${file.path}\\n${file.content}\\n`);\n }\n\n for (const file of context.derivedFiles) {\n if (file.path.endsWith('.json')) {\n parts.push(`## ${file.path}\\n\\`\\`\\`json\\n${file.content.slice(0, 2000)}\\n\\`\\`\\`\\n`);\n } else {\n parts.push(`## ${file.path}\\n${file.content}\\n`);\n }\n }\n\n return textResult(parts.join('\\n'));\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n },\n );\n\n server.tool(\n 'context_search',\n 'Search across all context files',\n { query: z.string().describe('Search query') },\n async ({ query }) => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n const results = await indexer.search(query);\n await eventClient.emit('mcp_query_executed', { tool: 'context_search' });\n\n if (results.length === 0) {\n return textResult('No results found');\n }\n\n const text = results\n .map(\n (result) =>\n `[${result.matchType}] ${result.filePath}${result.section ? ` > ${result.section}` : ''} (score: ${result.score})\\n${result.content}\\n`,\n )\n .join('\\n---\\n');\n\n return textResult(text);\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n },\n );\n\n server.tool(\n 'context_read_file',\n 'Read a specific context file',\n { file_path: z.string().describe('Path to the context file') },\n async ({ file_path }) => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n const content = await contextManager.readFile(file_path);\n return textResult(content);\n } catch (err) {\n return textResult(`Error reading file: ${err}`, true);\n }\n },\n );\n\n server.tool(\n 'context_read_section',\n 'Read a specific section from a context file',\n {\n file_path: z.string().describe('Path to the context file'),\n section_name: z.string().describe('Name of the section to read'),\n },\n async ({ file_path, section_name }) => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n const section = await contextManager.readSection(file_path, section_name);\n if (!section) {\n return textResult(`Section \"${section_name}\" not found in ${file_path}`);\n }\n return textResult(section);\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n },\n );\n\n server.tool(\n 'context_list_recent_updates',\n 'List recent context update proposals',\n { limit: z.number().optional().describe('Maximum number of updates to return') },\n async ({ limit }) => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n const updates = await contextManager.listRecentUpdates(limit ?? 10);\n if (updates.length === 0) {\n return textResult('No recent updates');\n }\n return textResult(JSON.stringify(updates, null, 2));\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n },\n );\n\n server.tool(\n 'context_get_daily_summary',\n 'Get the daily summary for a specific date',\n { date: z.string().optional().describe('Date in YYYY-MM-DD format (defaults to today)') },\n async ({ date }) => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n const summary = await contextManager.getDailySummary(date);\n if (!summary) {\n return textResult(`No daily summary found for ${date ?? 'today'}`);\n }\n return textResult(summary);\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n },\n );\n\n server.tool(\n 'context_propose_update',\n 'Propose an update to a context file',\n {\n target_file: z.string().describe('Path to the target file'),\n section: z.string().optional().describe('Section name to update (omit for full file)'),\n proposed_content: z.string().describe('The proposed new content'),\n reason: z.string().describe('Reason for the update'),\n },\n async ({ target_file, section, proposed_content, reason }) => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n const proposal = await contextManager.proposeUpdate({\n targetFile: target_file,\n section,\n proposedContent: proposed_content,\n reason,\n });\n await eventClient.emit('context_update_proposed');\n return textResult(\n `Update proposal created: ${proposal.id}\\nTarget: ${proposal.targetFile}\\nReason: ${proposal.reason}\\nStatus: ${proposal.status}`,\n );\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n },\n );\n\n server.tool(\n 'context_apply_update',\n 'Apply a pending update proposal',\n { proposal_id: z.string().describe('ID of the proposal to apply') },\n async ({ proposal_id }) => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n const applied = await contextManager.applyUpdate(proposal_id);\n await eventClient.emit('context_update_applied');\n return textResult(\n `Update applied: ${applied.id}\\nTarget: ${applied.targetFile}\\nApplied at: ${applied.appliedAt}`,\n );\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n },\n );\n\n server.tool(\n 'context_append_note',\n 'Append a note to a project context file',\n {\n project_name: z.string().describe('The project name'),\n note: z.string().describe('The note to append'),\n },\n async ({ project_name, note }) => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n await contextManager.appendNote(project_name, note);\n return textResult(`Note appended to project: ${project_name}`);\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n },\n );\n\n server.tool('context_rebuild_indexes', 'Rebuild all context indexes', {}, async () => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n await indexer.buildIndexes();\n return textResult('Indexes rebuilt successfully');\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n });\n\n server.tool(\n 'session_end',\n 'End the current session: force-apply all pending proposals, save session notes, rebuild indexes, and clear the active project',\n {\n project_name: z.string().optional().describe('The active project name'),\n session_notes: z.string().optional().describe('Summary of what was learned or decided during this session'),\n },\n async ({ project_name, session_notes }) => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n const results: string[] = [];\n\n const appliedIds = await contextManager.applyAllPending();\n if (appliedIds.length > 0) {\n results.push(`Applied ${appliedIds.length} pending proposal(s): ${appliedIds.join(', ')}`);\n } else {\n results.push('No pending proposals to apply.');\n }\n\n if (session_notes && project_name) {\n await contextManager.appendNote(project_name, session_notes);\n results.push(`Session notes saved to project: ${project_name}`);\n }\n\n await indexer.buildIndexes();\n results.push('Indexes rebuilt.');\n\n await configManager.setActiveProject('');\n results.push('Active project cleared.');\n\n const timestamp = new Date().toISOString();\n const logEntry = `[${timestamp}] Session ended for project \"${project_name ?? 'none'}\". Applied ${appliedIds.length} proposals.\\n`;\n await storage.append('logs/audit.log', logEntry);\n\n return textResult(`Session ended successfully.\\n\\n${results.join('\\n')}`);\n } catch (err) {\n return textResult(`Error ending session: ${err}`, true);\n }\n },\n );\n\n server.tool('sync_run_now', 'Trigger an immediate sync', {}, async () => {\n const unavailable = await ensureStorageAvailable();\n if (unavailable) return unavailable;\n try {\n await indexer.buildIndexes();\n return textResult('Sync completed. Indexes rebuilt.');\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n });\n\n server.tool('sync_status', 'Get the current sync status', {}, async () => {\n await storageReady;\n try {\n const config = getStatusConfig();\n const integrations = config.integrations\n .filter((integration) => integration.enabled)\n .map((integration) => {\n const health = getIntegrationHealth(integration.type);\n return {\n type: integration.type,\n lastSyncAt: integration.lastSyncAt ?? 'never',\n cursor: integration.cursor ?? 'none',\n connectionStatus: health?.status ?? 'healthy',\n connectionSummary: health?.summary ?? `No startup health check recorded for ${integration.type}`,\n connectionReason: health?.reason ?? null,\n fix: health?.fix ?? [],\n restart: health?.restart ?? DEFAULT_RESTART_STEPS,\n };\n });\n\n const status = {\n syncTime: config.sync.dailySyncTime,\n timezone: config.sync.timezone,\n storage: {\n mode: runtimeHealth.storage.mode,\n status: runtimeHealth.storage.status,\n summary: runtimeHealth.storage.summary,\n reason: runtimeHealth.storage.reason ?? null,\n fix: runtimeHealth.storage.fix,\n restart: runtimeHealth.storage.restart,\n },\n integrations,\n alerts: runtimeHealth.alerts,\n };\n\n return textResult(JSON.stringify(status, null, 2));\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n });\n\n server.tool('sync_list_integrations', 'List all configured integrations', {}, async () => {\n await storageReady;\n try {\n const config = getStatusConfig();\n const list = config.integrations.map((integration) => {\n const health = getIntegrationHealth(integration.type);\n const connection = health\n ? health.status === 'healthy'\n ? `healthy - ${health.summary}`\n : `error - ${health.reason ?? health.summary}`\n : 'not checked';\n return `${integration.type}: ${integration.enabled ? 'enabled' : 'disabled'} (connection: ${connection}; last sync: ${integration.lastSyncAt ?? 'never'})`;\n });\n\n return textResult(list.join('\\n') || 'No integrations configured');\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n });\n\n server.tool(\n 'events_ping',\n 'Emit a metadata-only event',\n {\n event_name: z.string().describe('Name of the event'),\n metadata: z.record(z.string()).optional().describe('Optional metadata key-value pairs'),\n },\n async ({ event_name, metadata }) => {\n await storageReady;\n try {\n await eventClient.emit(event_name as any, metadata);\n return textResult(`Event emitted: ${event_name}`);\n } catch (err) {\n return textResult(`Error: ${err}`, true);\n }\n },\n );\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n await resolveStorageBackend();\n storageReadyResolve?.();\n}\n"],"mappings":"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","names":["fs","path","resolve"]}
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
installCodexMcp,
|
|
5
5
|
resolvePacmanServerCommand,
|
|
6
6
|
startMcpServer
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-WH3UMGHQ.js";
|
|
8
8
|
import {
|
|
9
9
|
createIndexer
|
|
10
10
|
} from "./chunk-3QNXXON5.js";
|
|
@@ -36,6 +36,8 @@ var TOOL_GROUPS = [
|
|
|
36
36
|
"- Sync: `sync_run_now`, `sync_status`, `sync_list_integrations`",
|
|
37
37
|
"- Events: `events_ping`"
|
|
38
38
|
];
|
|
39
|
+
var MCP_SERVER_NAME = "pacman";
|
|
40
|
+
var CLAUDE_START_COMMAND = "/pacman start <project_name>";
|
|
39
41
|
function getStorageDescription(config) {
|
|
40
42
|
return config.storage.mode === "local" ? `Local workspace at: ${config.storage.workspacePath}` : `Google Drive folder: ${config.storage.folderName} (ID: ${config.storage.folderId})`;
|
|
41
43
|
}
|
|
@@ -58,7 +60,7 @@ Read context in this order:
|
|
|
58
60
|
## Retrieval rule
|
|
59
61
|
|
|
60
62
|
When the user asks about responsibilities, projects, stakeholders, status, history, routines, or prior decisions:
|
|
61
|
-
- Call the
|
|
63
|
+
- Call the Pac-Man MCP tools first
|
|
62
64
|
- Use \`context_search\` to find relevant files
|
|
63
65
|
- Use \`context_read_file\` or \`context_read_section\` for specific content
|
|
64
66
|
- Answer only from retrieved context files
|
|
@@ -80,7 +82,7 @@ When the conversation creates stable new context (new ownership, priority change
|
|
|
80
82
|
|
|
81
83
|
## MCP usage
|
|
82
84
|
|
|
83
|
-
This project uses the
|
|
85
|
+
This project uses the Pac-Man MCP server. All context operations go through MCP tools:
|
|
84
86
|
${TOOL_GROUPS.join("\n")}
|
|
85
87
|
|
|
86
88
|
## User profile
|
|
@@ -91,14 +93,14 @@ ${TOOL_GROUPS.join("\n")}
|
|
|
91
93
|
`;
|
|
92
94
|
}
|
|
93
95
|
function buildClaudeProjectMemory(config) {
|
|
94
|
-
return `#
|
|
96
|
+
return `# Pac-Man Project Rules
|
|
95
97
|
|
|
96
98
|
This project uses a local or Google Drive based context manager.
|
|
97
99
|
|
|
98
100
|
${buildSharedProjectSections(config)}`;
|
|
99
101
|
}
|
|
100
102
|
function buildCodexProjectGuidance(config) {
|
|
101
|
-
return `#
|
|
103
|
+
return `# Pac-Man Project Instructions
|
|
102
104
|
|
|
103
105
|
This repository uses a local or Google Drive based context manager.
|
|
104
106
|
|
|
@@ -106,30 +108,30 @@ ${buildSharedProjectSections(config)}
|
|
|
106
108
|
|
|
107
109
|
## Codex startup rule
|
|
108
110
|
|
|
109
|
-
- If
|
|
111
|
+
- If Pac-Man MCP tools are unavailable, tell the user to run \`pacman mcp codex install\`
|
|
110
112
|
- If the package is not installed globally, show the fallback command:
|
|
111
|
-
\`codex mcp add
|
|
113
|
+
\`codex mcp add ${MCP_SERVER_NAME} --env PA_WORKSPACE=$HOME/.personal-assistant -- npx -y pacman mcp serve\`
|
|
112
114
|
- Tell the user to restart Codex after installing or updating the MCP registration
|
|
113
115
|
`;
|
|
114
116
|
}
|
|
115
117
|
function buildClaudeSkillContent() {
|
|
116
118
|
return `---
|
|
117
|
-
name:
|
|
118
|
-
description: Start the
|
|
119
|
+
name: pacman
|
|
120
|
+
description: Start the Pac-Man workflow for a project using local or Google Drive context through MCP.
|
|
119
121
|
argument-hint: start [project_name]
|
|
120
|
-
allowed-tools:
|
|
122
|
+
allowed-tools: mcp__pacman__*
|
|
121
123
|
---
|
|
122
124
|
|
|
123
|
-
#
|
|
125
|
+
# Pac-Man Skill
|
|
124
126
|
|
|
125
|
-
When this skill is invoked with
|
|
127
|
+
When this skill is invoked with \`${CLAUDE_START_COMMAND}\`:
|
|
126
128
|
|
|
127
129
|
## Steps
|
|
128
130
|
|
|
129
131
|
1. **Check MCP availability**:
|
|
130
|
-
- If
|
|
132
|
+
- If Pac-Man MCP tools are unavailable, stop and tell the user to install them with \`pacman mcp claude install\`
|
|
131
133
|
- If the package is not installed globally, show the fallback command:
|
|
132
|
-
\`claude mcp add -s user --env=PA_WORKSPACE=$HOME/.personal-assistant
|
|
134
|
+
\`claude mcp add -s user --env=PA_WORKSPACE=$HOME/.personal-assistant ${MCP_SERVER_NAME} -- npx -y pacman mcp serve\`
|
|
133
135
|
- Tell the user to restart Claude Code after installing or updating the MCP registration
|
|
134
136
|
|
|
135
137
|
2. **Check MCP health**:
|
|
@@ -170,20 +172,20 @@ When this skill is invoked with \`/personal-assistant start <project_name>\`:
|
|
|
170
172
|
}
|
|
171
173
|
function buildCodexSkillContent() {
|
|
172
174
|
return `---
|
|
173
|
-
name:
|
|
174
|
-
description: Use when the user asks to start, load, refresh, or inspect
|
|
175
|
+
name: pacman
|
|
176
|
+
description: Use when the user asks to start, load, refresh, or inspect Pac-Man project context stored through the Pac-Man MCP workspace.
|
|
175
177
|
---
|
|
176
178
|
|
|
177
|
-
#
|
|
179
|
+
# Pac-Man
|
|
178
180
|
|
|
179
|
-
Use this skill when the user asks to load or refresh
|
|
181
|
+
Use this skill when the user asks to load or refresh Pac-Man context for a project.
|
|
180
182
|
|
|
181
183
|
## Steps
|
|
182
184
|
|
|
183
185
|
1. **Check MCP availability**:
|
|
184
|
-
- If
|
|
186
|
+
- If Pac-Man MCP tools are unavailable, stop and tell the user to install them with \`pacman mcp codex install\`
|
|
185
187
|
- If the package is not installed globally, show the fallback command:
|
|
186
|
-
\`codex mcp add
|
|
188
|
+
\`codex mcp add ${MCP_SERVER_NAME} --env PA_WORKSPACE=$HOME/.personal-assistant -- npx -y pacman mcp serve\`
|
|
187
189
|
- Tell the user to restart Codex after installing or updating the MCP registration
|
|
188
190
|
|
|
189
191
|
2. **Check MCP health**:
|
|
@@ -234,12 +236,14 @@ async function generateClaudeMd(projectPath, config) {
|
|
|
234
236
|
await fs.writeFile(path.join(projectPath, "CLAUDE.md"), buildClaudeProjectMemory(config), "utf-8");
|
|
235
237
|
}
|
|
236
238
|
async function generateGlobalSkill() {
|
|
237
|
-
const
|
|
239
|
+
const skillsRoot = path.join(
|
|
238
240
|
process.env.HOME ?? process.env.USERPROFILE ?? "~",
|
|
239
241
|
".claude",
|
|
240
|
-
"skills"
|
|
241
|
-
"personal-assistant"
|
|
242
|
+
"skills"
|
|
242
243
|
);
|
|
244
|
+
const legacySkillDir = path.join(skillsRoot, "personal-assistant");
|
|
245
|
+
const globalSkillDir = path.join(skillsRoot, "pacman");
|
|
246
|
+
await fs.rm(legacySkillDir, { recursive: true, force: true });
|
|
243
247
|
await fs.mkdir(globalSkillDir, { recursive: true });
|
|
244
248
|
await fs.writeFile(path.join(globalSkillDir, "SKILL.md"), buildClaudeSkillContent(), "utf-8");
|
|
245
249
|
}
|
|
@@ -263,12 +267,14 @@ async function generateAgentsMd(projectPath, config) {
|
|
|
263
267
|
);
|
|
264
268
|
}
|
|
265
269
|
async function generateGlobalSkill2() {
|
|
266
|
-
const
|
|
270
|
+
const skillsRoot = path2.join(
|
|
267
271
|
process.env.HOME ?? process.env.USERPROFILE ?? "~",
|
|
268
272
|
".codex",
|
|
269
|
-
"skills"
|
|
270
|
-
"personal-assistant"
|
|
273
|
+
"skills"
|
|
271
274
|
);
|
|
275
|
+
const legacySkillDir = path2.join(skillsRoot, "personal-assistant");
|
|
276
|
+
const globalSkillDir = path2.join(skillsRoot, "pacman");
|
|
277
|
+
await fs2.rm(legacySkillDir, { recursive: true, force: true });
|
|
272
278
|
await fs2.mkdir(globalSkillDir, { recursive: true });
|
|
273
279
|
await fs2.writeFile(
|
|
274
280
|
path2.join(globalSkillDir, "SKILL.md"),
|
|
@@ -291,11 +297,11 @@ async function resolveWorkspacePath(dirOpt) {
|
|
|
291
297
|
return path3.resolve(dirOpt);
|
|
292
298
|
}
|
|
293
299
|
var program = new Command();
|
|
294
|
-
program.name("pacman").description("Claude Code and Codex compatible, file-backed personal context manager").version("0.1.
|
|
295
|
-
program.command("init").description("Initialize
|
|
300
|
+
program.name("pacman").description("Claude Code and Codex compatible, file-backed personal context manager").version("0.1.3");
|
|
301
|
+
program.command("init").description("Initialize Pac-Man and open onboarding UI").option("-p, --port <port>", "Port for onboarding server", "3847").option("-d, --dir <dir>", "Workspace directory", ".personal-assistant").action(async (opts) => {
|
|
296
302
|
const workspacePath = path3.resolve(opts.dir);
|
|
297
303
|
const port = parseInt(opts.port, 10);
|
|
298
|
-
console.log(`Initializing
|
|
304
|
+
console.log(`Initializing Pac-Man workspace at ${workspacePath}...`);
|
|
299
305
|
await fs3.mkdir(workspacePath, { recursive: true });
|
|
300
306
|
const storage = createLocalStorage(workspacePath);
|
|
301
307
|
const contextManager = createContextManager(storage);
|
|
@@ -338,13 +344,13 @@ program.command("claude").description("Claude integration management").command("
|
|
|
338
344
|
});
|
|
339
345
|
console.log("Claude Code integration installed:");
|
|
340
346
|
console.log(` - ${projectPath}/CLAUDE.md`);
|
|
341
|
-
console.log(` - ~/.claude/skills/
|
|
347
|
+
console.log(` - ~/.claude/skills/pacman/SKILL.md`);
|
|
342
348
|
console.log("");
|
|
343
349
|
console.log("Next, register the MCP server with:");
|
|
344
350
|
console.log(" pacman mcp claude install");
|
|
345
351
|
console.log("");
|
|
346
352
|
console.log("Restart Claude Code after the MCP install, then use:");
|
|
347
|
-
console.log(" /
|
|
353
|
+
console.log(" /pacman start <project_name>");
|
|
348
354
|
});
|
|
349
355
|
program.command("codex").description("Codex integration management").command("install").description("Install Codex integration (AGENTS.md, skill)").option("-d, --dir <dir>", "Project directory", ".").option("-w, --workspace <workspace>", "Workspace directory", ".personal-assistant").action(async (opts) => {
|
|
350
356
|
const projectPath = path3.resolve(opts.dir);
|
|
@@ -368,38 +374,36 @@ program.command("codex").description("Codex integration management").command("in
|
|
|
368
374
|
});
|
|
369
375
|
console.log("Codex integration installed:");
|
|
370
376
|
console.log(` - ${projectPath}/AGENTS.md`);
|
|
371
|
-
console.log(` - ~/.codex/skills/
|
|
377
|
+
console.log(` - ~/.codex/skills/pacman/SKILL.md`);
|
|
372
378
|
console.log("");
|
|
373
379
|
console.log("Next, register the MCP server with:");
|
|
374
380
|
console.log(" pacman mcp codex install");
|
|
375
381
|
console.log("");
|
|
376
382
|
console.log("Restart Codex after the MCP install, then ask it to load or refresh");
|
|
377
|
-
console.log("your
|
|
383
|
+
console.log("your Pac-Man context for a project.");
|
|
378
384
|
});
|
|
379
385
|
var mcpCommand = program.command("mcp").description("MCP server management");
|
|
380
|
-
mcpCommand.command("serve").description("Start the
|
|
386
|
+
mcpCommand.command("serve").description("Start the Pac-Man MCP server over stdio").option("-w, --workspace <workspace>", "Workspace directory", ".personal-assistant").action(async (opts) => {
|
|
381
387
|
const workspacePath = await resolveWorkspacePath(opts.workspace);
|
|
382
388
|
await startMcpServer(workspacePath);
|
|
383
389
|
});
|
|
384
|
-
mcpCommand.command("claude").description("Claude MCP integration management").command("install").description("Register the
|
|
390
|
+
mcpCommand.command("claude").description("Claude MCP integration management").command("install").description("Register the Pac-Man MCP server with Claude Code").option("-w, --workspace <workspace>", "Workspace directory", ".personal-assistant").action(async (opts) => {
|
|
385
391
|
const workspacePath = await resolveWorkspacePath(opts.workspace);
|
|
386
392
|
await installClaudeMcp(workspacePath, resolvePacmanServerCommand);
|
|
387
393
|
console.log("Claude MCP registration installed:");
|
|
388
394
|
console.log(" - managed by Claude Code CLI");
|
|
389
395
|
console.log(` - PA_WORKSPACE=${workspacePath}`);
|
|
390
396
|
console.log("");
|
|
391
|
-
console.log("Restart Claude Code to reload the
|
|
392
|
-
console.log("Legacy alias still available: personal-assistant-mcp claude install");
|
|
397
|
+
console.log("Restart Claude Code to reload the Pac-Man MCP server.");
|
|
393
398
|
});
|
|
394
|
-
mcpCommand.command("codex").description("Codex MCP integration management").command("install").description("Register the
|
|
399
|
+
mcpCommand.command("codex").description("Codex MCP integration management").command("install").description("Register the Pac-Man MCP server with Codex").option("-w, --workspace <workspace>", "Workspace directory", ".personal-assistant").action(async (opts) => {
|
|
395
400
|
const workspacePath = await resolveWorkspacePath(opts.workspace);
|
|
396
401
|
await installCodexMcp(workspacePath, resolvePacmanServerCommand);
|
|
397
402
|
console.log("Codex MCP registration installed:");
|
|
398
403
|
console.log(" - managed by Codex CLI");
|
|
399
404
|
console.log(` - PA_WORKSPACE=${workspacePath}`);
|
|
400
405
|
console.log("");
|
|
401
|
-
console.log("Restart Codex to reload the
|
|
402
|
-
console.log("Legacy alias still available: personal-assistant-mcp codex install");
|
|
406
|
+
console.log("Restart Codex to reload the Pac-Man MCP server.");
|
|
403
407
|
});
|
|
404
408
|
program.command("sync").description("Run a one-time sync").option("-d, --dir <dir>", "Workspace directory", ".personal-assistant").action(async (opts) => {
|
|
405
409
|
const workspacePath = await resolveWorkspacePath(opts.dir);
|