@pathmode/cli 2.0.0 → 2.0.2

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.
Files changed (3) hide show
  1. package/README.md +189 -25
  2. package/dist/index.js +23 -7
  3. package/package.json +4 -5
package/README.md CHANGED
@@ -1,38 +1,202 @@
1
- # IntentSpec Validation Action
1
+ # @pathmode/cli
2
2
 
3
- The official GitHub Action for [IntentSpec](https://intentspec.org) the open standard for Spec-Driven Development.
3
+ The command-line interface for [Pathmode](https://pathmode.io). It syncs your repo's agent context files with your Pathmode workspace, pushes implementation status back, and validates specs against the [IntentSpec](https://intentspec.org/spec) standard.
4
4
 
5
- Use this action to enforce **Functional Guardrails** in your CI/CD pipeline. It validates that your `intent.md` exists and adheres to the [IntentSpec Schema](https://intentspec.org/schema.json).
5
+ ## Install
6
6
 
7
- ## Usage
7
+ ```bash
8
+ npm i -g @pathmode/cli
9
+ ```
10
+
11
+ This installs the `pathmode` binary. Check it with:
12
+
13
+ ```bash
14
+ pathmode --version
15
+ ```
16
+
17
+ You can also run it without installing:
18
+
19
+ ```bash
20
+ npx @pathmode/cli validate
21
+ ```
22
+
23
+ ## Quick start
24
+
25
+ ```bash
26
+ npm i -g @pathmode/cli
27
+ pathmode login # paste your pm_live_ API key
28
+ pathmode init # write intent.md, .cursorrules, CLAUDE.md
29
+ ```
30
+
31
+ `validate` works with no account. The other five commands talk to the Pathmode API and need a key.
32
+
33
+ ## Authentication
34
+
35
+ 1. Open your Pathmode workspace, go to **Workspace Settings > API Keys**, and create a key. Keys start with `pm_live_`.
36
+ 2. Run `pathmode login`. With no flags it prompts for the key and workspace ID, verifies them against the API, and reports the workspace it connected to.
37
+
38
+ ```bash
39
+ pathmode login
40
+ # or non-interactively:
41
+ pathmode login --key pm_live_xxx --workspace <workspace-id>
42
+ ```
43
+
44
+ Credentials are written to `~/.pathmode/config.json` with `0600` permissions.
45
+
46
+ ### Environment variables
47
+
48
+ Environment variables take precedence over the config file, so use them in CI instead of committing a config:
49
+
50
+ | Variable | Purpose | Default |
51
+ |---|---|---|
52
+ | `PATHMODE_API_KEY` | API key (`pm_live_...`) | none |
53
+ | `PATHMODE_API_URL` | API base URL | `https://pathmode.io` |
54
+ | `PATHMODE_WORKSPACE_ID` | Workspace ID | none |
55
+
56
+ ## Commands
57
+
58
+ | Command | What it does | Needs auth |
59
+ |---|---|---|
60
+ | [`validate`](#validate-file) | Check a spec against the IntentSpec schema | No |
61
+ | [`login`](#login) | Store and verify your API key | Sets it up |
62
+ | [`init`](#init) | Scaffold intent files in a fresh repo | Yes |
63
+ | [`pull`](#pull) | Refresh local context files from the workspace | Yes |
64
+ | [`push`](#push) | Send status changes and notes back | Yes |
65
+ | [`status`](#status) | List workspace intents and their status | Yes |
66
+
67
+ ### `validate [file]`
68
+
69
+ Validates the YAML frontmatter of a markdown file against the [IntentSpec schema](https://intentspec.org/schema.json). Exits `0` when valid and `1` when not, printing each failed field, so it works as a CI gate.
70
+
71
+ ```bash
72
+ pathmode validate # defaults to intent.md
73
+ pathmode validate specs/login.md
74
+ ```
75
+
76
+ Required fields are `id`, `status`, `objective`, and `outcomes`. `status` must be one of `draft`, `validated`, `approved`, `shipped`, or `verified`. See the [full standard](https://intentspec.org/spec) for the optional fields.
77
+
78
+ ### `login`
79
+
80
+ | Option | Description | Default |
81
+ |---|---|---|
82
+ | `--key <key>` | API key, starting with `pm_live_` | prompts |
83
+ | `--workspace <id>` | Workspace ID | prompts |
84
+ | `--url <url>` | Pathmode API URL | `https://pathmode.io` |
85
+
86
+ If the connection test fails the config is still saved, so you can fix the network and retry with `pathmode pull`.
87
+
88
+ ### `init`
89
+
90
+ Pulls your workspace context and writes three files into the current directory:
91
+
92
+ - `intent.md`, the current intent spec
93
+ - `.cursorrules`, rules for Cursor
94
+ - `CLAUDE.md`, workspace context for Claude Code
8
95
 
9
- Add this to your workflow file (e.g., `.github/workflows/intentspec.yml`):
96
+ ```bash
97
+ pathmode init
98
+ pathmode init --dry-run # preview without writing
99
+ pathmode init --intent abc-123 # use a specific intent
100
+ ```
101
+
102
+ | Option | Description |
103
+ |---|---|
104
+ | `--intent <id>` | Use a specific intent instead of the current approved one |
105
+ | `--dry-run` | Print what would be written and exit |
106
+
107
+ ### `pull`
108
+
109
+ Re-syncs the files `init` created. Run it whenever the spec changes upstream.
110
+
111
+ ```bash
112
+ pathmode pull
113
+ pathmode pull --only claude-md,intent-md
114
+ pathmode pull --only agents-md
115
+ ```
116
+
117
+ | Option | Description |
118
+ |---|---|
119
+ | `--intent <id>` | Pull a specific intent |
120
+ | `--only <files>` | Comma-separated subset of `claude-md`, `agents-md`, `cursorrules`, `intent-md` |
121
+
122
+ `AGENTS.md` is opt-in. It carries the same context as `CLAUDE.md`, so syncing it by default would only duplicate that file. Request it with `--only agents-md` if you use OpenAI Codex or a recent Cursor version.
123
+
124
+ ### `push`
125
+
126
+ Reports progress back to the workspace. The intent ID comes from the `id` in your local `intent.md` frontmatter unless you pass `--intent`.
127
+
128
+ ```bash
129
+ pathmode push --shipped
130
+ pathmode push --verified
131
+ pathmode push --note "Rate limiting added in middleware, not the route handler"
132
+ ```
133
+
134
+ | Option | Description |
135
+ |---|---|
136
+ | `--shipped` | Mark the intent as shipped |
137
+ | `--verified` | Mark the intent as verified |
138
+ | `--note <text>` | Log an implementation note against the intent |
139
+ | `--intent <id>` | Target a specific intent |
140
+
141
+ ### `status`
142
+
143
+ Lists the workspace's intents with their status, severity, and stage.
144
+
145
+ ```bash
146
+ pathmode status
147
+ pathmode status --filter approved
148
+ ```
149
+
150
+ | Option | Description |
151
+ |---|---|
152
+ | `--filter <status>` | One of `draft`, `validated`, `approved`, `shipped`, `verified` |
153
+
154
+ ## How CLAUDE.md is updated
155
+
156
+ `init` and `pull` do not overwrite `CLAUDE.md` or `AGENTS.md`. They replace only the block between these markers, leaving your own notes and conventions intact:
157
+
158
+ ```markdown
159
+ <!-- PATHMODE:START - Do not edit this section manually -->
160
+ ... generated content ...
161
+ <!-- PATHMODE:END -->
162
+ ```
163
+
164
+ If the markers are absent the section is appended. `.cursorrules` and `intent.md` are fully replaced on every sync.
165
+
166
+ ## Using it in CI
167
+
168
+ Validate every spec on a pull request:
169
+
170
+ ```yaml
171
+ - uses: actions/checkout@v4
172
+ - run: npx @pathmode/cli validate intent.md
173
+ ```
174
+
175
+ Keep context files fresh on a schedule, using repository secrets for the credentials:
10
176
 
11
177
  ```yaml
12
- name: Validate IntentSpec
178
+ - run: npm i -g @pathmode/cli
179
+ - run: pathmode pull
180
+ env:
181
+ PATHMODE_API_KEY: ${{ secrets.PATHMODE_API_KEY }}
182
+ PATHMODE_WORKSPACE_ID: ${{ secrets.PATHMODE_WORKSPACE_ID }}
183
+ ```
13
184
 
14
- on: [push, pull_request]
185
+ This package also ships an `action.yml`, so the same bundle runs directly as a GitHub Action that validates a spec. It reads the `file` input, defaulting to `intent.md`.
15
186
 
16
- jobs:
17
- validate:
18
- runs-on: ubuntu-latest
19
- steps:
20
- - uses: actions/checkout@v4
21
-
22
- - name: Validate Intent Spec
23
- uses: JanneL/validate-intentspec-action@v1
24
- with:
25
- file: 'intent.md' # Optional (default: intent.md)
187
+ ```yaml
188
+ - uses: JanneL/validate-intentspec-action@v1
189
+ with:
190
+ file: 'intent.md'
26
191
  ```
27
192
 
28
- ## Inputs
193
+ ## IntentSpec
194
+
195
+ `validate` checks against IntentSpec, the open standard for describing what a change is supposed to accomplish before an agent writes the code.
29
196
 
30
- | Input | Description | Default | Required |
31
- | :--- | :--- | :--- | :--- |
32
- | `file` | Path to the intent markdown file | `intent.md` | No |
197
+ - Standard: <https://intentspec.org/spec>
198
+ - JSON Schema: <https://intentspec.org/schema.json>
33
199
 
34
- ## Why use this?
200
+ ## License
35
201
 
36
- 1. **Prevent Drift:** Ensure AI agents (and humans) have a clear definition of "Done".
37
- 2. **Enforce Structure:** Validate that `objective`, `outcomes`, and `constraints` are defined.
38
- 3. **Governance:** Make IntentSpecs a required part of your PR process.
202
+ MIT
package/dist/index.js CHANGED
@@ -11150,6 +11150,11 @@ class PathmodeClient {
11150
11150
  const res = await this.fetch('/export?format=claude-md');
11151
11151
  return res.text();
11152
11152
  }
11153
+ /** Export AGENTS.md content (same workspace context as CLAUDE.md, for Codex / modern Cursor) */
11154
+ async exportAgentsMd() {
11155
+ const res = await this.fetch('/export?format=agents-md');
11156
+ return res.text();
11157
+ }
11153
11158
  /** Export .cursorrules content */
11154
11159
  async exportCursorRules(intentId) {
11155
11160
  const params = intentId ? `?format=cursorrules&intent_id=${intentId}` : '?format=cursorrules';
@@ -11207,7 +11212,7 @@ const isGitHubAction = !!process.env.GITHUB_ACTIONS || !!process.env.INPUT_FILE;
11207
11212
  program
11208
11213
  .name('pathmode')
11209
11214
  .description('Pathmode CLI — Intent Engineering for AI product teams')
11210
- .version('2.0.0');
11215
+ .version('2.0.2');
11211
11216
  // ============================================================
11212
11217
  // validate — Existing command (preserved)
11213
11218
  // ============================================================
@@ -11353,7 +11358,7 @@ program
11353
11358
  console.log(chalk_1.default.green(`\u2705 Written: ${cursorPath}`));
11354
11359
  // Write or update CLAUDE.md
11355
11360
  const claudePath = path_1.default.join(cwd, 'CLAUDE.md');
11356
- writeClaudeMdSection(claudePath, claudeMd);
11361
+ writePathmodeSection(claudePath, claudeMd);
11357
11362
  console.log(chalk_1.default.green(`\u2705 Written: ${claudePath}`));
11358
11363
  console.log(chalk_1.default.cyan('\n\u2728 Project initialized with Pathmode intent context!'));
11359
11364
  console.log(chalk_1.default.gray('Run `pathmode pull` to update these files later.'));
@@ -11370,7 +11375,7 @@ program
11370
11375
  .command('pull')
11371
11376
  .description('Pull latest intent data from Pathmode and update local files')
11372
11377
  .option('--intent <id>', 'Specific intent ID to pull')
11373
- .option('--only <files>', 'Only update specific files (claude-md,cursorrules,intent-md)', '')
11378
+ .option('--only <files>', 'Only update specific files (claude-md,agents-md,cursorrules,intent-md)', '')
11374
11379
  .action(async (options) => {
11375
11380
  console.log(chalk_1.default.cyan('\n\u2b07\ufe0f Pathmode Pull\n'));
11376
11381
  const config = (0, api_client_1.loadConfig)();
@@ -11387,9 +11392,20 @@ program
11387
11392
  console.log(chalk_1.default.gray('Pulling CLAUDE.md content...'));
11388
11393
  const claudeMd = await client.exportClaudeMd();
11389
11394
  const claudePath = path_1.default.join(cwd, 'CLAUDE.md');
11390
- writeClaudeMdSection(claudePath, claudeMd);
11395
+ writePathmodeSection(claudePath, claudeMd);
11391
11396
  console.log(chalk_1.default.green(`\u2705 Updated: CLAUDE.md`));
11392
11397
  }
11398
+ // AGENTS.md is opt-in (Codex / modern Cursor). It carries the same
11399
+ // agent-agnostic context as CLAUDE.md, so syncing it by default would
11400
+ // just duplicate CLAUDE.md \u2014 only write it when explicitly requested
11401
+ // via --only agents-md.
11402
+ if (onlyFiles.includes('agents-md')) {
11403
+ console.log(chalk_1.default.gray('Pulling AGENTS.md content...'));
11404
+ const agentsMd = await client.exportAgentsMd();
11405
+ const agentsPath = path_1.default.join(cwd, 'AGENTS.md');
11406
+ writePathmodeSection(agentsPath, agentsMd);
11407
+ console.log(chalk_1.default.green(`\u2705 Updated: AGENTS.md`));
11408
+ }
11393
11409
  if (shouldUpdate('cursorrules')) {
11394
11410
  console.log(chalk_1.default.gray('Pulling .cursorrules...'));
11395
11411
  const cursorRules = await client.exportCursorRules(options.intent);
@@ -11511,10 +11527,10 @@ program
11511
11527
  const PATHMODE_START = '<!-- PATHMODE:START - Do not edit this section manually -->';
11512
11528
  const PATHMODE_END = '<!-- PATHMODE:END -->';
11513
11529
  /**
11514
- * Write Pathmode section into CLAUDE.md, preserving any existing content
11515
- * outside the PATHMODE:START/END markers.
11530
+ * Write the Pathmode section into a CLAUDE.md / AGENTS.md style file,
11531
+ * preserving any existing content outside the PATHMODE:START/END markers.
11516
11532
  */
11517
- function writeClaudeMdSection(filePath, pathmodeContent) {
11533
+ function writePathmodeSection(filePath, pathmodeContent) {
11518
11534
  if (fs_1.default.existsSync(filePath)) {
11519
11535
  const existing = fs_1.default.readFileSync(filePath, 'utf-8');
11520
11536
  const startIdx = existing.indexOf(PATHMODE_START);
package/package.json CHANGED
@@ -1,6 +1,9 @@
1
1
  {
2
2
  "name": "@pathmode/cli",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
4
7
  "description": "The Intent Layer CLI — Spec-Driven Development with Pathmode",
5
8
  "main": "dist/index.js",
6
9
  "bin": {
@@ -25,10 +28,6 @@
25
28
  "author": "Pathmode",
26
29
  "license": "MIT",
27
30
  "type": "commonjs",
28
- "repository": {
29
- "type": "git",
30
- "url": "git+https://github.com/pathmode/cli.git"
31
- },
32
31
  "homepage": "https://pathmode.io",
33
32
  "devDependencies": {
34
33
  "@types/fs-extra": "^11.0.4",