mantisai-cli 3.0.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,6 +10,7 @@ Full docs (VitePress):
10
10
  - [Install](https://mantis.csail.mit.edu/docs/mantis-cli/install)
11
11
  - [Claude Code](https://mantis.csail.mit.edu/docs/mantis-cli/claude-code)
12
12
  - [OpenCode](https://mantis.csail.mit.edu/docs/mantis-cli/opencode)
13
+ - [Codex](https://mantis.csail.mit.edu/docs/mantis-cli/codex)
13
14
 
14
15
  Source: `Mantis/docs/mantis-cli/`
15
16
 
@@ -33,7 +34,7 @@ Config: `~/.mantis/config.json`
33
34
 
34
35
  | Command | Description |
35
36
  | --- | --- |
36
- | `mantis setup [claude\|opencode]` | API + space/thread, or sync editor skills |
37
+ | `mantis setup [claude\|opencode\|codex]` | API + space/thread, or sync editor skills |
37
38
  | `mantis status` | Current config |
38
39
  | `mantis select [space\|thread\|both]` | Switch space/thread |
39
40
  | `mantis spaces list\|resolve\|set` | Scriptable space ops (JSON) |
package/bin/mantis.js CHANGED
@@ -104,7 +104,7 @@ program
104
104
 
105
105
  .description('Mantis CLI — spaces, maps, and MCP tools for AI agents')
106
106
 
107
- .version('3.0.0');
107
+ .version('3.0.1');
108
108
 
109
109
 
110
110
 
@@ -112,15 +112,17 @@ program
112
112
 
113
113
  .command('setup [provider]')
114
114
 
115
- .description('Configure Mantis, or install skills for claude/opencode')
115
+ .description('Configure Mantis, or install skills for claude/opencode/codex')
116
116
 
117
- .action(async (provider) => {
117
+ .option('--project', 'Also sync repo-scoped skills (Codex: ./.agents/skills/)')
118
+
119
+ .action(async (provider, opts) => {
118
120
 
119
121
  try {
120
122
 
121
123
  if (!provider) return setup.run();
122
124
 
123
- setup.runProvider(provider);
125
+ setup.runProvider(provider, { project: !!opts.project });
124
126
 
125
127
  } catch (e) {
126
128
 
package/lib/container.js CHANGED
@@ -7,6 +7,7 @@ import { FastGlobCodebaseIndexer } from './impl/fast-glob-codebase-indexer.js';
7
7
  import { FsCsvReader } from './impl/fs-csv-reader.js';
8
8
  import { ClaudeSkillsService } from './impl/claude-skills-service.js';
9
9
  import { OpencodeSkillsService } from './impl/opencode-skills-service.js';
10
+ import { CodexSkillsService } from './impl/codex-skills-service.js';
10
11
  import { SelectionService } from './services/selection-service.js';
11
12
  import { SetupService } from './services/setup-service.js';
12
13
  import { MapService } from './services/map-service.js';
@@ -24,9 +25,10 @@ export function createContainer(overrides = {}) {
24
25
  const csvReader = overrides.csvReader ?? new FsCsvReader();
25
26
  const claudeSkills = overrides.claudeSkills ?? new ClaudeSkillsService();
26
27
  const opencodeSkills = overrides.opencodeSkills ?? new OpencodeSkillsService();
28
+ const codexSkills = overrides.codexSkills ?? new CodexSkillsService();
27
29
 
28
30
  const selection = new SelectionService({ configStore, spaces, client, ui });
29
- const setup = new SetupService({ configStore, selection, claudeSkills, opencodeSkills, ui });
31
+ const setup = new SetupService({ configStore, selection, claudeSkills, opencodeSkills, codexSkills, ui });
30
32
  const map = new MapService({ configStore, client, spaces, csvReader, ui });
31
33
  const query = new QueryService({ configStore, spaces });
32
34
  const context = new ContextService({ configStore });
@@ -42,6 +44,7 @@ export function createContainer(overrides = {}) {
42
44
  csvReader,
43
45
  claudeSkills,
44
46
  opencodeSkills,
47
+ codexSkills,
45
48
  selection,
46
49
  setup,
47
50
  map,
@@ -0,0 +1,19 @@
1
+ import os from 'node:os';
2
+ import path from 'node:path';
3
+
4
+ import { SKILLS_DIR } from '../utils/package-root.js';
5
+ import { syncSkills } from '../utils/skills-sync.js';
6
+
7
+ export class CodexSkillsService {
8
+ sync(cwd = process.cwd(), { project = false } = {}) {
9
+ const globalSkillsDir = path.join(os.homedir(), '.agents', 'skills');
10
+ const targets = [globalSkillsDir];
11
+ let projectSkillsDir;
12
+ if (project) {
13
+ projectSkillsDir = path.join(cwd, '.agents', 'skills');
14
+ targets.push(projectSkillsDir);
15
+ }
16
+ const installed = syncSkills({ skillsDir: SKILLS_DIR, targets });
17
+ return { globalSkillsDir, projectSkillsDir, installed };
18
+ }
19
+ }
@@ -24,7 +24,7 @@ export class McpClientService {
24
24
  const transport = new StreamableHTTPClientTransport(new URL(mcpUrl(cfg)), {
25
25
  requestInit: { headers: this._headers(cfg) },
26
26
  });
27
- const client = new Client({ name: 'mantisai-cli', version: '3.0.0' });
27
+ const client = new Client({ name: 'mantisai-cli', version: '3.0.1' });
28
28
  await client.connect(transport);
29
29
  try {
30
30
  return await fn(client);
@@ -1,14 +1,15 @@
1
1
  import { DEFAULT_API_BASE, DEVELOPER_PORTAL_URL } from '../constants.js';
2
2
  import { normalizeBaseUrl, mcpUrl } from '../utils/url.js';
3
3
 
4
- const PROVIDERS = new Set(['claude', 'opencode']);
4
+ const PROVIDERS = new Set(['claude', 'opencode', 'codex']);
5
5
 
6
6
  export class SetupService {
7
- constructor({ configStore, selection, claudeSkills, opencodeSkills, ui }) {
7
+ constructor({ configStore, selection, claudeSkills, opencodeSkills, codexSkills, ui }) {
8
8
  this.configStore = configStore;
9
9
  this.selection = selection;
10
10
  this.claudeSkills = claudeSkills;
11
11
  this.opencodeSkills = opencodeSkills;
12
+ this.codexSkills = codexSkills;
12
13
  this.ui = ui;
13
14
  }
14
15
 
@@ -51,14 +52,14 @@ export class SetupService {
51
52
  this.ui.info(`Thread: ${cfg.spaceStateName || '-'} (${cfg.spaceStateId || '-'})`);
52
53
  this.ui.info(`MCP: ${mcpUrl(cfg)}`);
53
54
  this.ui.info('Explore with: mantis tools && mantis use get_space_context');
54
- this.ui.info('Editor skills: mantis setup claude | mantis setup opencode');
55
+ this.ui.info('Editor skills: mantis setup claude | opencode | codex');
55
56
  console.log('');
56
57
  }
57
58
 
58
- runProvider(provider) {
59
+ runProvider(provider, { project = false } = {}) {
59
60
  const p = String(provider || '').toLowerCase();
60
61
  if (!PROVIDERS.has(p)) {
61
- throw new Error(`Unknown provider "${provider}". Use: claude, opencode`);
62
+ throw new Error(`Unknown provider "${provider}". Use: claude, opencode, codex`);
62
63
  }
63
64
 
64
65
  if (p === 'claude') {
@@ -70,12 +71,28 @@ export class SetupService {
70
71
  return { provider: p, skillsDir, installed };
71
72
  }
72
73
 
73
- const { globalSkillsDir, projectSkillsDir, installed } = this.opencodeSkills.sync();
74
- this.ui.banner('Mantis skills → OpenCode');
74
+ if (p === 'opencode') {
75
+ const { globalSkillsDir, projectSkillsDir, installed } = this.opencodeSkills.sync();
76
+ this.ui.banner('Mantis skills → OpenCode');
77
+ this.ui.success(`Synced ${installed.length} skill(s)`);
78
+ this.ui.info(`Global: ${globalSkillsDir}`);
79
+ this.ui.info(`Project: ${projectSkillsDir}`);
80
+ for (const s of installed) this.ui.info(`${s.slash} ← skills/${s.source}`);
81
+ return { provider: p, globalSkillsDir, projectSkillsDir, installed };
82
+ }
83
+
84
+ const { globalSkillsDir, projectSkillsDir, installed } = this.codexSkills.sync(undefined, { project });
85
+ this.ui.banner('Mantis skills → Codex');
75
86
  this.ui.success(`Synced ${installed.length} skill(s)`);
76
- this.ui.info(`Global: ${globalSkillsDir}`);
77
- this.ui.info(`Project: ${projectSkillsDir}`);
78
- for (const s of installed) this.ui.info(`${s.slash} ← skills/${s.source}`);
87
+ this.ui.info(`USER: ${globalSkillsDir}`);
88
+ if (projectSkillsDir) {
89
+ this.ui.info(`REPO: ${projectSkillsDir}`);
90
+ this.ui.info('Same skill names in USER + REPO may appear twice in Codex; disable one via /skills if needed.');
91
+ } else {
92
+ this.ui.info('Repo copy skipped. Re-run with --project to also write ./.agents/skills/ for team commit.');
93
+ }
94
+ for (const s of installed) this.ui.info(`$${s.name} ← skills/${s.source}`);
95
+ this.ui.info('Invoke with $mantis or /skills. Restart Codex if new skills do not appear.');
79
96
  return { provider: p, globalSkillsDir, projectSkillsDir, installed };
80
97
  }
81
98
  }
@@ -23,6 +23,9 @@ export function prepareSkillContent(content, installName) {
23
23
  yaml = /^name:\s/m.test(yaml)
24
24
  ? yaml.replace(/^name:\s.*$/m, `name: ${installName}`)
25
25
  : `name: ${installName}\n${yaml}`;
26
+ if (!/^description:\s/m.test(yaml)) {
27
+ yaml = `${yaml}\ndescription: Mantis CLI skill (${installName}).`;
28
+ }
26
29
  return `---\n${yaml}\n---${body}`;
27
30
  }
28
31
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mantisai-cli",
3
- "version": "3.0.0",
3
+ "version": "3.0.1",
4
4
  "description": "Mantis CLI — spaces, maps, and MCP tools for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -33,6 +33,7 @@ Install editor skills (CLI-only workflow, no MCP plugin):
33
33
  ```bash
34
34
  mantis setup claude # ~/.claude/skills/
35
35
  mantis setup opencode # ~/.config/opencode/skills/ + .opencode/skills/
36
+ mantis setup codex # ~/.agents/skills/ (add --project for ./.agents/skills/)
36
37
  ```
37
38
 
38
39
  ## MCP tools via CLI