@neturely/okffs 0.8.0 → 0.10.0
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/CHANGELOG.md +16 -1
- package/README.md +27 -2
- package/dist/autopilot.d.ts +16 -0
- package/dist/autopilot.d.ts.map +1 -0
- package/dist/autopilot.js +42 -0
- package/dist/autopilot.js.map +1 -0
- package/dist/cli/banner.d.ts +17 -0
- package/dist/cli/banner.d.ts.map +1 -0
- package/dist/cli/banner.js +65 -0
- package/dist/cli/banner.js.map +1 -0
- package/dist/cli/env.d.ts +30 -0
- package/dist/cli/env.d.ts.map +1 -0
- package/dist/cli/env.js +171 -0
- package/dist/cli/env.js.map +1 -0
- package/dist/cli/index.d.ts +12 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +77 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/manifest.d.ts +48 -0
- package/dist/cli/manifest.d.ts.map +1 -0
- package/dist/cli/manifest.js +312 -0
- package/dist/cli/manifest.js.map +1 -0
- package/dist/cli/probe.d.ts +32 -0
- package/dist/cli/probe.d.ts.map +1 -0
- package/dist/cli/probe.js +101 -0
- package/dist/cli/probe.js.map +1 -0
- package/dist/cli/sanity.d.ts +16 -0
- package/dist/cli/sanity.d.ts.map +1 -0
- package/dist/cli/sanity.js +99 -0
- package/dist/cli/sanity.js.map +1 -0
- package/dist/cli/setup.d.ts +2 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +254 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +13 -0
- package/dist/config.js.map +1 -1
- package/dist/github.d.ts +1 -0
- package/dist/github.d.ts.map +1 -1
- package/dist/github.js +53 -6
- package/dist/github.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -107
- package/dist/index.js.map +1 -1
- package/dist/prompts/setup.d.ts +18 -0
- package/dist/prompts/setup.d.ts.map +1 -0
- package/dist/prompts/setup.js +77 -0
- package/dist/prompts/setup.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +183 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/commit_and_update.d.ts +3 -0
- package/dist/tools/commit_and_update.d.ts.map +1 -1
- package/dist/tools/commit_and_update.js +6 -0
- package/dist/tools/commit_and_update.js.map +1 -1
- package/dist/tools/configure.d.ts +27 -0
- package/dist/tools/configure.d.ts.map +1 -0
- package/dist/tools/configure.js +91 -0
- package/dist/tools/configure.js.map +1 -0
- package/dist/tools/create_issue.d.ts.map +1 -1
- package/dist/tools/create_issue.js +24 -4
- package/dist/tools/create_issue.js.map +1 -1
- package/dist/tools/create_pull_request.d.ts +3 -0
- package/dist/tools/create_pull_request.d.ts.map +1 -1
- package/dist/tools/create_pull_request.js +9 -0
- package/dist/tools/create_pull_request.js.map +1 -1
- package/dist/tools/plan.d.ts.map +1 -1
- package/dist/tools/plan.js +11 -2
- package/dist/tools/plan.js.map +1 -1
- package/dist/tools/update_project_status.d.ts +2 -2
- package/package.json +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,19 @@ See [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.10.0] - 2026-07-14
|
|
9
|
+
### Added
|
|
10
|
+
- Autopilot / "minimum interference" mode — autonomous issue → develop-PR with a decisions report ([#238](https://github.com/neturely/okffs/issues/238))
|
|
11
|
+
### Fixed
|
|
12
|
+
- Silent auto-PR failure in create_issue - swallowed to stderr, retry on 422 ([#247](https://github.com/neturely/okffs/issues/247))
|
|
13
|
+
|
|
14
|
+
## [0.9.0] - 2026-07-11
|
|
15
|
+
### Changed
|
|
16
|
+
- commit_and_update: empty commit subject from whitespace-only or leading-blank-line hint ([#236](https://github.com/neturely/okffs/issues/236))
|
|
17
|
+
### Added
|
|
18
|
+
- `/okffs:setup` prompt + `configure` tool — configure okffs conversationally inside Claude Code (the in-chat counterpart to the `okffs setup` CLI). Claude interviews you from the same manifest the CLI uses and persists via `configure`, which writes only okffs's marked `.env` block and preserves your own variables/comments. On startup the server also stamps the configuring version and, when okffs has been upgraded and new options exist, nudges you (once) to run `/okffs:setup` ([#242](https://github.com/neturely/okffs/issues/242))
|
|
19
|
+
- `okffs setup` — an interactive CLI wizard to create/update `.env` for a repo, with Quick/Full first-run modes and a sync mode that only prompts for options new since your last run (e.g. after an okffs upgrade). Runs a non-fatal GitHub sanity check and prints a config banner. Reach it via `npx @neturely/okffs setup` ([#240](https://github.com/neturely/okffs/issues/240))
|
|
20
|
+
|
|
8
21
|
## [0.8.0] - 2026-07-08
|
|
9
22
|
### Added
|
|
10
23
|
- Add an issue-less "fix PR into base branch" tool (open + merge into develop, the mirror of promote_branch) ([#226](https://github.com/neturely/okffs/issues/226))
|
|
@@ -144,7 +157,9 @@ See [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
144
157
|
- `create_pull_request` commits the updated CHANGELOG onto the branch and pushes the branch before opening the PR, with non-blocking error handling ([#38](https://github.com/2b9sa2owa/okffs/issues/38)).
|
|
145
158
|
- All git operations now run via `execFileSync` with argument arrays (no shell), removing command-injection risk from branch names and commit hints; tools also checkout the target branch before committing/pushing and restore the original branch afterward.
|
|
146
159
|
|
|
147
|
-
[Unreleased]: https://github.com/neturely/okffs/compare/v0.
|
|
160
|
+
[Unreleased]: https://github.com/neturely/okffs/compare/v0.10.0...HEAD
|
|
161
|
+
[0.10.0]: https://github.com/neturely/okffs/compare/v0.9.0...v0.10.0
|
|
162
|
+
[0.9.0]: https://github.com/neturely/okffs/compare/v0.8.0...v0.9.0
|
|
148
163
|
[0.8.0]: https://github.com/neturely/okffs/compare/v0.7.0...v0.8.0
|
|
149
164
|
[0.7.0]: https://github.com/neturely/okffs/compare/v0.6.0...v0.7.0
|
|
150
165
|
[0.6.0]: https://github.com/neturely/okffs/compare/v0.5.2...v0.6.0
|
package/README.md
CHANGED
|
@@ -15,7 +15,17 @@ okffs is a [Model Context Protocol](https://modelcontextprotocol.io) server that
|
|
|
15
15
|
|
|
16
16
|
## Quick start
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
**1. Run the setup wizard** from your project root:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx @neturely/okffs setup
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
It walks you through auth, repo, and any optional features, writes a `.env`, then runs a quick GitHub sanity check. Re-run it any time (e.g. after upgrading okffs) — it only asks about options that are new since your last run. If you're happy relying on the [GitHub CLI](https://cli.github.com/) (`gh auth login`) and working inside the repo you want to manage, you can skip this step entirely — okffs works with **no config at all**.
|
|
25
|
+
|
|
26
|
+
> **Already in Claude Code?** Once okffs is connected you can configure it conversationally instead — run the **`/okffs:setup`** slash command and Claude will interview you and write the `.env` for you (no terminal needed). okffs also nudges you to run it after an upgrade introduces new options.
|
|
27
|
+
|
|
28
|
+
**2. Add a `.mcp.json`** to your project root:
|
|
19
29
|
|
|
20
30
|
```json
|
|
21
31
|
{
|
|
@@ -28,7 +38,7 @@ Add a `.mcp.json` to your project root:
|
|
|
28
38
|
}
|
|
29
39
|
```
|
|
30
40
|
|
|
31
|
-
That's it — `npx` fetches okffs on first use, and Claude Code picks up the tools automatically.
|
|
41
|
+
That's it — `npx` fetches okffs on first use, and Claude Code picks up the tools automatically. To use a token or a different repo instead of the `gh`/auto-detect defaults, run `okffs setup` (above) or edit `.env` by hand — see [Configuration](#configuration).
|
|
32
42
|
|
|
33
43
|
Now just ask Claude:
|
|
34
44
|
|
|
@@ -64,6 +74,7 @@ Claude infers labels (`bug`, `enhancement`, …) from the title and description
|
|
|
64
74
|
| `update_project_status` | Moves an issue between board columns (`Backlog`, `Ready`, `In Progress`, `Review`). Needs `OKFFS_PROJECT_ENABLED`. |
|
|
65
75
|
| `set_issue_fields` | Sets board Priority/Effort **and/or the native Issue Type** on an **existing** issue. Priority/Effort handle project-native and org-level Issue Fields (needs `OKFFS_PROJECT_ENABLED`); `type` is org-native and works independently. `create_issue` only sets these at creation; use this afterwards. Status stays with `update_project_status`. |
|
|
66
76
|
| `update_issue` | Edits an **existing** issue's core fields — `title`, `assignees`, `labels`, `milestone`, `body` — via one PATCH with the configured token. `labels`/`assignees` replace the whole set (`[]` clears). For Priority/Effort/Type use `set_issue_fields`; for Status use `update_project_status`. |
|
|
77
|
+
| `configure` | Writes okffs config to `.env` — the backend for the `/okffs:setup` prompt. Reuses the `okffs setup` wizard's manifest/serializer: updates only okffs's marked block, preserving your own variables and comments. Usually driven by `/okffs:setup`, not called directly. |
|
|
67
78
|
| `delete_issue` | Closes an issue **and** deletes its branch. Destructive — needs `confirmed: true`. |
|
|
68
79
|
| `delete_branch` | Deletes a branch **and** closes its issue. Destructive — needs `confirmed: true`. |
|
|
69
80
|
|
|
@@ -75,6 +86,12 @@ okffs has a built-in loop for review feedback — just ask (*"address the review
|
|
|
75
86
|
|
|
76
87
|
By default review threads are left open for you to resolve; set `OKFFS_RESOLVE_THREADS=true` to have okffs resolve them once addressed.
|
|
77
88
|
|
|
89
|
+
## Autopilot (minimum interference)
|
|
90
|
+
|
|
91
|
+
For a hands-off session, ask Claude to *"fully handle this"* (or *"minimum interference"*) — or set `OKFFS_AUTOPILOT=true` to make it the default. In autopilot, Claude stops asking you to choose between options for **reversible** decisions, takes the recommended option at each fork, and drives an issue all the way to a PR into the base branch (and a base merge when `OKFFS_AUTO_MERGE_BASE=true`) — then posts an **"Autopilot decisions"** report (one line per choice, with a one-line why) to the PR and the issue, so you can redirect anything in a single message.
|
|
92
|
+
|
|
93
|
+
It removes confirmation friction; it does **not** grant new powers. The hard stops always interrupt, even in autopilot: anything into `OKFFS_PROTECTED_BRANCH` (merge/tag/publish), destructive tools (`delete_issue` / `delete_branch`), anything billable (e.g. a Copilot review on a new promotion PR), and genuinely irreversible actions. And for a real *missing-information* call — where only you hold the context — Claude still asks one quick question rather than guess. Off by default.
|
|
94
|
+
|
|
78
95
|
## Keeping CLAUDE.md in sync
|
|
79
96
|
|
|
80
97
|
The **`/okffs:update_guidance`** slash command reviews the changes on the current branch and maintains one okffs-owned section of your `CLAUDE.md` — `## Project Guidance (okffs usage)`, delimited by HTML markers — without ever touching your hand-written content. It's guidance curation (tools, env vars, conventions), not a changelog. Set `OKFFS_UPDATE_GUIDANCE=true` to have `create_pull_request` nudge Claude to run it at PR time; the command is always available.
|
|
@@ -107,6 +124,8 @@ Once enabled, `list_issues` shows each issue's column, priority, and effort (ord
|
|
|
107
124
|
|
|
108
125
|
## Configuration
|
|
109
126
|
|
|
127
|
+
The quickest way to configure okffs is the wizard — `npx @neturely/okffs setup` — which writes and maintains the `.env` described below for you. The rest of this section documents what it (or you, by hand) can set.
|
|
128
|
+
|
|
110
129
|
okffs resolves a **token** and a **target repository** with fallbacks, so most users need little config.
|
|
111
130
|
|
|
112
131
|
**Token** (first match wins):
|
|
@@ -185,6 +204,12 @@ All optional; unset unless noted. Grouped by concern — the same groups appear
|
|
|
185
204
|
| `OKFFS_PROMOTION_REVIEWERS` | — | Comma-separated reviewers to request on the gate PR (e.g. `copilot-pull-request-reviewer[bot]`). Only acted on when `OKFFS_PROMOTION_AUTO_REVIEW=true`. |
|
|
186
205
|
| `OKFFS_PROMOTION_AUTO_REVIEW` | `false` | Opt in to auto-request those reviewers, **on gate-PR creation only** (never on re-runs). **⚠️ Cost:** Copilot code review is billable, so this charges per newly-created promotion PR. |
|
|
187
206
|
|
|
207
|
+
**Autopilot (minimum interference)**
|
|
208
|
+
|
|
209
|
+
| Variable | Default | Purpose |
|
|
210
|
+
|----------|---------|---------|
|
|
211
|
+
| `OKFFS_AUTOPILOT` | `false` | Default the session to [autopilot](#autopilot-minimum-interference): take the recommended option at each reversible fork, drive to a base-branch PR, and report the decisions. Hard stops (protected branch, destructive, billable, irreversible) still interrupt. Per-request activation (*"fully handle this"*) works regardless. |
|
|
212
|
+
|
|
188
213
|
## Conventions
|
|
189
214
|
|
|
190
215
|
- **Branches:** `{issue-number}-{kebab-title-slug}` (title truncated to ~5 words), e.g. `42-add-hero-section-to-homepage`.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether minimum-interference mode is on by env default (OKFFS_AUTOPILOT=true).
|
|
3
|
+
* Per-request activation ("fully handle this") is behavioural and not visible
|
|
4
|
+
* here — this only reflects the persistent default.
|
|
5
|
+
*/
|
|
6
|
+
export declare function autopilotEnabled(): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Render the "Autopilot decisions" report block — one line per fork, each already
|
|
9
|
+
* phrased by the agent as *what was chosen* + *one-line why*. Returns null when
|
|
10
|
+
* there is nothing to report so callers omit the section cleanly rather than
|
|
11
|
+
* emitting an empty heading. Blank/whitespace-only entries are dropped. #238.
|
|
12
|
+
*/
|
|
13
|
+
export declare function renderAutopilotDecisions(decisions?: string[] | null): string | null;
|
|
14
|
+
/** Shared schema description for the `autopilot_decisions` tool parameter. */
|
|
15
|
+
export declare const AUTOPILOT_DECISIONS_DESCRIPTION: string;
|
|
16
|
+
//# sourceMappingURL=autopilot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autopilot.d.ts","sourceRoot":"","sources":["../src/autopilot.ts"],"names":[],"mappings":"AAaA;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAQnF;AAED,8EAA8E;AAC9E,eAAO,MAAM,+BAA+B,QAKmC,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Autopilot ("minimum interference") — #238.
|
|
2
|
+
//
|
|
3
|
+
// The mode itself is behavioural: okffs can't suppress the host LLM's questions,
|
|
4
|
+
// so the load-bearing piece is the always-on guidance in SERVER_INSTRUCTIONS
|
|
5
|
+
// (src/server.ts), which tells the agent to take the recommended option at each
|
|
6
|
+
// reversible fork, honour the hard stops, and report the decisions. This module
|
|
7
|
+
// is the small amount of *plumbing* okffs owns: knowing whether the env default
|
|
8
|
+
// is on, and rendering the decisions report into a PR body / issue comment in a
|
|
9
|
+
// consistent shape (the host LLM supplies the content — the decisions — the same
|
|
10
|
+
// way it supplies triage/fixes for address_pr_review).
|
|
11
|
+
import { config } from "./config.js";
|
|
12
|
+
/**
|
|
13
|
+
* Whether minimum-interference mode is on by env default (OKFFS_AUTOPILOT=true).
|
|
14
|
+
* Per-request activation ("fully handle this") is behavioural and not visible
|
|
15
|
+
* here — this only reflects the persistent default.
|
|
16
|
+
*/
|
|
17
|
+
export function autopilotEnabled() {
|
|
18
|
+
return config.autopilot;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Render the "Autopilot decisions" report block — one line per fork, each already
|
|
22
|
+
* phrased by the agent as *what was chosen* + *one-line why*. Returns null when
|
|
23
|
+
* there is nothing to report so callers omit the section cleanly rather than
|
|
24
|
+
* emitting an empty heading. Blank/whitespace-only entries are dropped. #238.
|
|
25
|
+
*/
|
|
26
|
+
export function renderAutopilotDecisions(decisions) {
|
|
27
|
+
// Strip a leading bullet marker (-, *, •) the caller may have already added, so
|
|
28
|
+
// "- chose X" and "chose X" both render as a single bullet rather than "- - …".
|
|
29
|
+
const items = (decisions ?? [])
|
|
30
|
+
.map((d) => d.trim().replace(/^[-*•]\s+/, "").trim())
|
|
31
|
+
.filter(Boolean);
|
|
32
|
+
if (items.length === 0)
|
|
33
|
+
return null;
|
|
34
|
+
return ["## 🤖 Autopilot decisions", ...items.map((d) => `- ${d}`)].join("\n");
|
|
35
|
+
}
|
|
36
|
+
/** Shared schema description for the `autopilot_decisions` tool parameter. */
|
|
37
|
+
export const AUTOPILOT_DECISIONS_DESCRIPTION = "Autopilot decisions report — when driving this issue in minimum-interference " +
|
|
38
|
+
"(autopilot) mode, pass one entry per reversible fork you decided without asking, " +
|
|
39
|
+
"each phrased as 'what you chose — one-line why'. okffs renders them as an " +
|
|
40
|
+
"'Autopilot decisions' block in the PR body and the issue comment so the user has " +
|
|
41
|
+
"an audit trail to redirect in a single message. Omit when not in autopilot.";
|
|
42
|
+
//# sourceMappingURL=autopilot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autopilot.js","sourceRoot":"","sources":["../src/autopilot.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,iFAAiF;AACjF,6EAA6E;AAC7E,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAChF,iFAAiF;AACjF,uDAAuD;AAEvD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,MAAM,CAAC,SAAS,CAAC;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,SAA2B;IAClE,gFAAgF;IAChF,gFAAgF;IAChF,MAAM,KAAK,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC;SAC5B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;SACpD,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO,CAAC,2BAA2B,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACjF,CAAC;AAED,8EAA8E;AAC9E,MAAM,CAAC,MAAM,+BAA+B,GAC1C,+EAA+E;IAC/E,mFAAmF;IACnF,4EAA4E;IAC5E,mFAAmF;IACnF,6EAA6E,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare function packageVersion(): string;
|
|
2
|
+
export interface BannerInfo {
|
|
3
|
+
version: string;
|
|
4
|
+
owner?: string;
|
|
5
|
+
repo?: string;
|
|
6
|
+
tokenSource: "env" | "gh" | "none";
|
|
7
|
+
baseBranch: string;
|
|
8
|
+
protectedBranch: string;
|
|
9
|
+
features: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare function buildBannerInfo(values: Record<string, string>, resolved: {
|
|
12
|
+
owner?: string;
|
|
13
|
+
repo?: string;
|
|
14
|
+
tokenSource: "env" | "gh" | "none";
|
|
15
|
+
}): BannerInfo;
|
|
16
|
+
export declare function renderBanner(info: BannerInfo): string;
|
|
17
|
+
//# sourceMappingURL=banner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"banner.d.ts","sourceRoot":"","sources":["../../src/cli/banner.ts"],"names":[],"mappings":"AAMA,wBAAgB,cAAc,IAAI,MAAM,CAQvC;AAWD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,KAAK,GAAG,IAAI,GAAG,MAAM,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,QAAQ,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,KAAK,GAAG,IAAI,GAAG,MAAM,CAAA;CAAE,GAC9E,UAAU,CAuBZ;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAWrD"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// The startup info banner: package version, resolved owner/repo, branch tiers,
|
|
2
|
+
// and which optional features are active. Factored out (plain string, no prompt
|
|
3
|
+
// library) so a future `okffs status` command can reuse it standalone.
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
export function packageVersion() {
|
|
6
|
+
try {
|
|
7
|
+
// dist/cli/banner.js → ../../package.json is the package root in both the
|
|
8
|
+
// published layout and local dist build.
|
|
9
|
+
return JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf8")).version;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return "unknown";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function isTrue(v) {
|
|
16
|
+
return v === "true";
|
|
17
|
+
}
|
|
18
|
+
// Booleans that default ON (OKFFS_*_METADATA/INFER) are "off" only at "false".
|
|
19
|
+
function isOff(v) {
|
|
20
|
+
return v === "false";
|
|
21
|
+
}
|
|
22
|
+
export function buildBannerInfo(values, resolved) {
|
|
23
|
+
const features = [];
|
|
24
|
+
if (isTrue(values.OKFFS_PROJECT_ENABLED))
|
|
25
|
+
features.push("Projects v2 board");
|
|
26
|
+
if (isTrue(values.OKFFS_AUTO_PR))
|
|
27
|
+
features.push("auto draft-PR on new issue");
|
|
28
|
+
if (isTrue(values.OKFFS_AUTO_MERGE_BASE))
|
|
29
|
+
features.push("auto-merge into base");
|
|
30
|
+
if (isTrue(values.OKFFS_UPDATE_DOCS))
|
|
31
|
+
features.push("auto doc updates");
|
|
32
|
+
if (isTrue(values.OKFFS_RESOLVE_THREADS))
|
|
33
|
+
features.push("auto-resolve review threads");
|
|
34
|
+
if (isTrue(values.OKFFS_UPDATE_GUIDANCE))
|
|
35
|
+
features.push("guidance sync");
|
|
36
|
+
if (isTrue(values.OKFFS_CLASSIC_PAT))
|
|
37
|
+
features.push("classic PAT (org Issue Fields)");
|
|
38
|
+
if (isTrue(values.OKFFS_PROMOTION_AUTO_REVIEW))
|
|
39
|
+
features.push("auto-request promotion reviewers");
|
|
40
|
+
if (isOff(values.OKFFS_INFER_PRIORITY) || isOff(values.OKFFS_INFER_EFFORT) || isOff(values.OKFFS_INFER_TYPE)) {
|
|
41
|
+
features.push("some inference disabled");
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
version: packageVersion(),
|
|
45
|
+
owner: resolved.owner,
|
|
46
|
+
repo: resolved.repo,
|
|
47
|
+
tokenSource: resolved.tokenSource,
|
|
48
|
+
baseBranch: values.OKFFS_BASE_BRANCH || "(repo default)",
|
|
49
|
+
protectedBranch: values.OKFFS_PROTECTED_BRANCH || "(none)",
|
|
50
|
+
features,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export function renderBanner(info) {
|
|
54
|
+
const tokenLabel = info.tokenSource === "env" ? "GITHUB_TOKEN" : info.tokenSource === "gh" ? "gh CLI" : "none";
|
|
55
|
+
const lines = [
|
|
56
|
+
`okffs v${info.version}`,
|
|
57
|
+
`repo: ${info.owner && info.repo ? `${info.owner}/${info.repo}` : "(unresolved)"}`,
|
|
58
|
+
`token: ${tokenLabel}`,
|
|
59
|
+
`base: ${info.baseBranch}`,
|
|
60
|
+
`protected: ${info.protectedBranch}`,
|
|
61
|
+
`features: ${info.features.length ? info.features.join(", ") : "defaults only"}`,
|
|
62
|
+
];
|
|
63
|
+
return lines.join("\n");
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=banner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"banner.js","sourceRoot":"","sources":["../../src/cli/banner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface ParsedEnv {
|
|
2
|
+
/** Whether the file existed at all. */
|
|
3
|
+
exists: boolean;
|
|
4
|
+
/** User content before okffs's managed block — preserved verbatim (okffs var lines migrated out). */
|
|
5
|
+
preamble: string;
|
|
6
|
+
/** User content after okffs's managed block — preserved verbatim (okffs var lines migrated out). */
|
|
7
|
+
postamble: string;
|
|
8
|
+
/** okffs var values found anywhere (managed block or migrated from user content), for seeding. */
|
|
9
|
+
values: Record<string, string>;
|
|
10
|
+
/** Every okffs key that appears, set OR as a `# KEY=` placeholder, anywhere in the file. */
|
|
11
|
+
known: Set<string>;
|
|
12
|
+
/** The okffs version stamped into the managed block last time it was written, if any. */
|
|
13
|
+
configuredVersion: string | null;
|
|
14
|
+
}
|
|
15
|
+
export declare function parseEnv(path: string): ParsedEnv;
|
|
16
|
+
export type EntryState = "set" | "declined";
|
|
17
|
+
export interface Entry {
|
|
18
|
+
state: EntryState;
|
|
19
|
+
value: string;
|
|
20
|
+
}
|
|
21
|
+
/** Keys absent from the map are "never asked" and omitted from the output. */
|
|
22
|
+
export type Collected = Record<string, Entry>;
|
|
23
|
+
/**
|
|
24
|
+
* Assemble the full .env: the preserved user preamble, then okffs's managed
|
|
25
|
+
* block (regenerated from the manifest + collected values), then the preserved
|
|
26
|
+
* user postamble. Only the managed block is okffs's to rewrite.
|
|
27
|
+
*/
|
|
28
|
+
export declare function serializeEnv(collected: Collected, preamble: string, postamble: string, version?: string): string;
|
|
29
|
+
export declare function writeEnv(path: string, contents: string): void;
|
|
30
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/cli/env.ts"],"names":[],"mappings":"AAiCA,MAAM,WAAW,SAAS;IACxB,uCAAuC;IACvC,MAAM,EAAE,OAAO,CAAC;IAChB,qGAAqG;IACrG,QAAQ,EAAE,MAAM,CAAC;IACjB,oGAAoG;IACpG,SAAS,EAAE,MAAM,CAAC;IAClB,kGAAkG;IAClG,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,4FAA4F;IAC5F,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,yFAAyF;IACzF,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAMD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAgDhD;AAkDD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,UAAU,CAAC;AAC5C,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,8EAA8E;AAC9E,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAQ9C;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CA0BhH;AAYD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAE7D"}
|
package/dist/cli/env.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// Reading and (re)writing .env for the setup wizard.
|
|
2
|
+
//
|
|
3
|
+
// okffs owns ONLY a marker-delimited block. Everything OUTSIDE the block — the
|
|
4
|
+
// user's own variables, their comments, their layout — is preserved verbatim
|
|
5
|
+
// across every run. Inside the block okffs regenerates its own variables in a
|
|
6
|
+
// fixed section order.
|
|
7
|
+
//
|
|
8
|
+
// <user content, preserved byte-for-byte>
|
|
9
|
+
// # okffs:env:start ── managed; regenerated each run ──
|
|
10
|
+
// OKFFS_… = …
|
|
11
|
+
// # okffs:env:end
|
|
12
|
+
// <more user content, preserved byte-for-byte>
|
|
13
|
+
//
|
|
14
|
+
// Recognized okffs variables found OUTSIDE the block (e.g. in a hand-written
|
|
15
|
+
// .env being adopted for the first time, or one copied from .env.example) are
|
|
16
|
+
// MIGRATED into the block: their value is read and re-emitted inside the block,
|
|
17
|
+
// and the stray line is removed so there is never a duplicate assignment. Their
|
|
18
|
+
// value is never lost — only relocated to the block okffs manages. Any comment
|
|
19
|
+
// that happened to sit directly above such a line stays where it was.
|
|
20
|
+
//
|
|
21
|
+
// The parser also powers sync mode: a variable counts as "known" whether it is
|
|
22
|
+
// set (`KEY=value`) or written as a declined placeholder (`# KEY=`), which is
|
|
23
|
+
// how sync distinguishes "asked and declined" from "new, never asked".
|
|
24
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
25
|
+
import { SECTIONS, allKeys } from "./manifest.js";
|
|
26
|
+
const KEY_RE = /^([A-Z][A-Z0-9_]*)=(.*)$/;
|
|
27
|
+
const COMMENTED_KEY_RE = /^#\s*([A-Z][A-Z0-9_]*)\s*=/;
|
|
28
|
+
const START_MARKER = "okffs:env:start";
|
|
29
|
+
const END_MARKER = "okffs:env:end";
|
|
30
|
+
// A version stamp okffs writes into the managed block so a later run can tell
|
|
31
|
+
// which okffs version last configured this .env (drives the upgrade nudge).
|
|
32
|
+
const VERSION_STAMP_RE = /okffs:configured-version=(\S+)/;
|
|
33
|
+
export function parseEnv(path) {
|
|
34
|
+
let raw;
|
|
35
|
+
try {
|
|
36
|
+
raw = readFileSync(path, "utf8");
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return { exists: false, preamble: "", postamble: "", values: {}, known: new Set(), configuredVersion: null };
|
|
40
|
+
}
|
|
41
|
+
const manifestKeys = new Set(allKeys());
|
|
42
|
+
const lines = raw.split("\n");
|
|
43
|
+
// Locate okffs's managed block by its markers.
|
|
44
|
+
const startIdx = lines.findIndex((l) => l.includes(START_MARKER));
|
|
45
|
+
const endIdx = lines.findIndex((l) => l.includes(END_MARKER));
|
|
46
|
+
let preLines;
|
|
47
|
+
let managedLines;
|
|
48
|
+
let postLines;
|
|
49
|
+
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
|
|
50
|
+
preLines = lines.slice(0, startIdx);
|
|
51
|
+
managedLines = lines.slice(startIdx + 1, endIdx);
|
|
52
|
+
postLines = lines.slice(endIdx + 1);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// No markers: the whole file is user content. okffs vars in it get migrated.
|
|
56
|
+
preLines = lines;
|
|
57
|
+
managedLines = [];
|
|
58
|
+
postLines = [];
|
|
59
|
+
}
|
|
60
|
+
const values = {};
|
|
61
|
+
const known = new Set();
|
|
62
|
+
// The managed block is discarded and regenerated; just harvest its values and
|
|
63
|
+
// the version stamp.
|
|
64
|
+
let configuredVersion = null;
|
|
65
|
+
for (const line of managedLines) {
|
|
66
|
+
const vm = line.match(VERSION_STAMP_RE);
|
|
67
|
+
if (vm)
|
|
68
|
+
configuredVersion = vm[1];
|
|
69
|
+
harvest(line, manifestKeys, values, known);
|
|
70
|
+
}
|
|
71
|
+
// From user content, migrate okffs var lines out (harvest + drop) and keep
|
|
72
|
+
// everything else — comments, blanks, custom vars, commented custom vars —
|
|
73
|
+
// byte-for-byte.
|
|
74
|
+
const preamble = migrate(preLines, manifestKeys, values, known);
|
|
75
|
+
const postamble = migrate(postLines, manifestKeys, values, known);
|
|
76
|
+
return { exists: true, preamble, postamble, values, known, configuredVersion };
|
|
77
|
+
}
|
|
78
|
+
// Record an okffs var line's key (+ value if set) without keeping the line.
|
|
79
|
+
function harvest(line, manifestKeys, values, known) {
|
|
80
|
+
const cm = line.match(COMMENTED_KEY_RE);
|
|
81
|
+
if (cm && manifestKeys.has(cm[1])) {
|
|
82
|
+
known.add(cm[1]);
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
const m = line.match(KEY_RE);
|
|
86
|
+
if (m && manifestKeys.has(m[1])) {
|
|
87
|
+
known.add(m[1]);
|
|
88
|
+
const v = unquote(m[2].trim());
|
|
89
|
+
if (v !== "" && values[m[1]] === undefined)
|
|
90
|
+
values[m[1]] = v; // first occurrence wins (dotenv semantics)
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
// Harvest okffs var lines out of `lines` and return the remaining lines
|
|
96
|
+
// (verbatim) joined back together.
|
|
97
|
+
function migrate(lines, manifestKeys, values, known) {
|
|
98
|
+
const kept = [];
|
|
99
|
+
for (const line of lines) {
|
|
100
|
+
if (harvest(line, manifestKeys, values, known))
|
|
101
|
+
continue; // okffs var — migrated into the block
|
|
102
|
+
kept.push(line); // user content — preserved
|
|
103
|
+
}
|
|
104
|
+
return kept.join("\n");
|
|
105
|
+
}
|
|
106
|
+
function unquote(v) {
|
|
107
|
+
if (v.length >= 2 && ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'")))) {
|
|
108
|
+
return v.slice(1, -1);
|
|
109
|
+
}
|
|
110
|
+
return v;
|
|
111
|
+
}
|
|
112
|
+
// Quote a value only when it needs it (spaces, #, or leading/trailing space),
|
|
113
|
+
// so simple values stay bare and readable.
|
|
114
|
+
function quoteIfNeeded(v) {
|
|
115
|
+
if (v === "")
|
|
116
|
+
return "";
|
|
117
|
+
if (/[\s#'"]/.test(v) || v !== v.trim())
|
|
118
|
+
return JSON.stringify(v);
|
|
119
|
+
return v;
|
|
120
|
+
}
|
|
121
|
+
// The block boundary is a SINGLE decorative line that CONTAINS the marker, so a
|
|
122
|
+
// re-parse slices exactly at it — no stray rule line can leak into the preserved
|
|
123
|
+
// user content and make the file grow on each run (regen must be idempotent).
|
|
124
|
+
const START_LINE = `# ${"═".repeat(22)} ${START_MARKER} ${"═".repeat(22)}`;
|
|
125
|
+
const END_LINE = `# ${"═".repeat(23)} ${END_MARKER} ${"═".repeat(24)}`;
|
|
126
|
+
/**
|
|
127
|
+
* Assemble the full .env: the preserved user preamble, then okffs's managed
|
|
128
|
+
* block (regenerated from the manifest + collected values), then the preserved
|
|
129
|
+
* user postamble. Only the managed block is okffs's to rewrite.
|
|
130
|
+
*/
|
|
131
|
+
export function serializeEnv(collected, preamble, postamble, version) {
|
|
132
|
+
const block = [
|
|
133
|
+
START_LINE,
|
|
134
|
+
"# Managed by `okffs setup` — regenerated on every run; set these via",
|
|
135
|
+
"# `okffs setup`, not by hand. Your own variables and comments OUTSIDE this",
|
|
136
|
+
"# block are left untouched.",
|
|
137
|
+
...(version ? [`# okffs:configured-version=${version}`] : []),
|
|
138
|
+
"",
|
|
139
|
+
];
|
|
140
|
+
for (const section of SECTIONS) {
|
|
141
|
+
const keys = [...(section.gateKey ? [section.gateKey] : []), ...section.vars.map((v) => v.key)];
|
|
142
|
+
if (!keys.some((k) => collected[k]))
|
|
143
|
+
continue; // whole section unasked — skip it
|
|
144
|
+
block.push(`# ${section.title}`);
|
|
145
|
+
if (section.blurb)
|
|
146
|
+
block.push(`# ${section.blurb}`);
|
|
147
|
+
for (const k of keys)
|
|
148
|
+
emitVar(block, k, collected);
|
|
149
|
+
block.push("");
|
|
150
|
+
}
|
|
151
|
+
block.push(END_LINE);
|
|
152
|
+
const pre = preamble.trim() ? preamble.replace(/\s+$/, "") + "\n\n" : "";
|
|
153
|
+
const post = postamble.trim() ? "\n" + postamble.replace(/^\s+/, "") : "";
|
|
154
|
+
const out = pre + block.join("\n") + post;
|
|
155
|
+
return out.replace(/\n{3,}/g, "\n\n").trimEnd() + "\n";
|
|
156
|
+
}
|
|
157
|
+
function emitVar(out, key, collected) {
|
|
158
|
+
const e = collected[key];
|
|
159
|
+
if (!e)
|
|
160
|
+
return; // never asked — omit so a later sync run offers it
|
|
161
|
+
if (e.state === "declined" || e.value === "") {
|
|
162
|
+
out.push(`# ${key}=`);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
out.push(`${key}=${quoteIfNeeded(e.value)}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
export function writeEnv(path, contents) {
|
|
169
|
+
writeFileSync(path, contents, "utf8");
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/cli/env.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "dotenv/config";
|
|
3
|
+
/** Subcommands that route to the CLI rather than the MCP server. */
|
|
4
|
+
export declare const SUBCOMMANDS: Set<string>;
|
|
5
|
+
/**
|
|
6
|
+
* Whether argv[2..] should be handled as a CLI invocation rather than starting
|
|
7
|
+
* the stdio MCP server. MCP hosts launch the server with no extra args, so a
|
|
8
|
+
* bare invocation always falls through to the server.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isCliInvocation(args: string[]): boolean;
|
|
11
|
+
export declare function runCli(args: string[]): Promise<number>;
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AASA,OAAO,eAAe,CAAC;AAMvB,oEAAoE;AACpE,eAAO,MAAM,WAAW,aAA8B,CAAC;AAIvD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAIvD;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA0B5D"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// okffs command-line entrypoint. Dispatches subcommands (currently `setup`) and
|
|
3
|
+
// is deliberately structured so `login` (Tier 3 OAuth Device Flow) and a future
|
|
4
|
+
// `status` slot in without reworking the dispatcher.
|
|
5
|
+
//
|
|
6
|
+
// Reachable two ways:
|
|
7
|
+
// npx @neturely/okffs setup → the package's single `okffs` bin is dist/index.js
|
|
8
|
+
// (the MCP server), which forwards CLI argv here.
|
|
9
|
+
// node dist/cli/index.js setup → this file run directly (local dev).
|
|
10
|
+
import "dotenv/config";
|
|
11
|
+
import { pathToFileURL } from "node:url";
|
|
12
|
+
import { runSetup } from "./setup.js";
|
|
13
|
+
import { packageVersion } from "./banner.js";
|
|
14
|
+
/** Subcommands that route to the CLI rather than the MCP server. */
|
|
15
|
+
export const SUBCOMMANDS = new Set(["setup", "login"]);
|
|
16
|
+
const HELP_FLAGS = new Set(["help", "--help", "-h"]);
|
|
17
|
+
const VERSION_FLAGS = new Set(["--version", "-v"]);
|
|
18
|
+
/**
|
|
19
|
+
* Whether argv[2..] should be handled as a CLI invocation rather than starting
|
|
20
|
+
* the stdio MCP server. MCP hosts launch the server with no extra args, so a
|
|
21
|
+
* bare invocation always falls through to the server.
|
|
22
|
+
*/
|
|
23
|
+
export function isCliInvocation(args) {
|
|
24
|
+
const first = args[0];
|
|
25
|
+
if (!first)
|
|
26
|
+
return false;
|
|
27
|
+
return SUBCOMMANDS.has(first) || HELP_FLAGS.has(first) || VERSION_FLAGS.has(first);
|
|
28
|
+
}
|
|
29
|
+
export async function runCli(args) {
|
|
30
|
+
const [sub, ...rest] = args;
|
|
31
|
+
if (VERSION_FLAGS.has(sub)) {
|
|
32
|
+
console.log(packageVersion());
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
if (!sub || HELP_FLAGS.has(sub)) {
|
|
36
|
+
printHelp();
|
|
37
|
+
return sub ? 0 : 1;
|
|
38
|
+
}
|
|
39
|
+
switch (sub) {
|
|
40
|
+
case "setup":
|
|
41
|
+
return runSetup(rest);
|
|
42
|
+
case "login":
|
|
43
|
+
console.error("`okffs login` (OAuth Device Flow) isn't implemented yet.\n" +
|
|
44
|
+
"For now, configure a GITHUB_TOKEN (or sign in with `gh auth login`) via `okffs setup`.");
|
|
45
|
+
return 1;
|
|
46
|
+
default:
|
|
47
|
+
console.error(`Unknown command: ${sub}\n`);
|
|
48
|
+
printHelp();
|
|
49
|
+
return 1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function printHelp() {
|
|
53
|
+
console.log([
|
|
54
|
+
`okffs v${packageVersion()} — GitHub issue → branch → PR → merge workflow for Claude Code`,
|
|
55
|
+
"",
|
|
56
|
+
"Usage:",
|
|
57
|
+
" npx @neturely/okffs <command>",
|
|
58
|
+
"",
|
|
59
|
+
"Commands:",
|
|
60
|
+
" setup Interactive wizard to create/update .env (run in a repo)",
|
|
61
|
+
" login (coming soon) OAuth Device Flow sign-in",
|
|
62
|
+
"",
|
|
63
|
+
"Flags:",
|
|
64
|
+
" -h, --help Show this help",
|
|
65
|
+
" -v, --version Print the okffs version",
|
|
66
|
+
"",
|
|
67
|
+
"With no command, okffs runs as an MCP server over stdio (how Claude Code launches it).",
|
|
68
|
+
].join("\n"));
|
|
69
|
+
}
|
|
70
|
+
// Run directly: `node dist/cli/index.js <args>`.
|
|
71
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
72
|
+
runCli(process.argv.slice(2)).then((code) => process.exit(code), (err) => {
|
|
73
|
+
console.error(err instanceof Error ? err.message : err);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export type VarKind = "text" | "boolean" | "secret" | "select";
|
|
2
|
+
export interface VarSpec {
|
|
3
|
+
key: string;
|
|
4
|
+
kind: VarKind;
|
|
5
|
+
/** One-line help shown at the prompt. */
|
|
6
|
+
description: string;
|
|
7
|
+
/** Default value (as it would appear in .env). Empty string = unset. */
|
|
8
|
+
default: string;
|
|
9
|
+
/** Allowed values for kind: "select". */
|
|
10
|
+
options?: string[];
|
|
11
|
+
/** Example value shown as placeholder for free-text vars. */
|
|
12
|
+
placeholder?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface Section {
|
|
15
|
+
id: string;
|
|
16
|
+
/** Header comment written into the generated .env. */
|
|
17
|
+
title: string;
|
|
18
|
+
/** Optional explanatory line under the header. */
|
|
19
|
+
blurb?: string;
|
|
20
|
+
vars: VarSpec[];
|
|
21
|
+
/**
|
|
22
|
+
* A gated section asks a single yes/no question first; declining it skips the
|
|
23
|
+
* whole group (its vars are written as commented placeholders). Auth & repo is
|
|
24
|
+
* the only ungated section — it is always asked.
|
|
25
|
+
*/
|
|
26
|
+
gated: boolean;
|
|
27
|
+
/** Prompt shown for the gate question. */
|
|
28
|
+
gatePrompt?: string;
|
|
29
|
+
/**
|
|
30
|
+
* For a section whose gate maps onto a real boolean env var (Projects), the
|
|
31
|
+
* gate answer is persisted to this key (true/false) rather than just toggling
|
|
32
|
+
* whether the sub-vars are asked.
|
|
33
|
+
*/
|
|
34
|
+
gateKey?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Only offer this section when the predicate holds against values collected so
|
|
37
|
+
* far (e.g. promotion is only relevant once a protected branch is set).
|
|
38
|
+
*/
|
|
39
|
+
onlyIf?: (values: Record<string, string>) => boolean;
|
|
40
|
+
}
|
|
41
|
+
export declare const SECTIONS: Section[];
|
|
42
|
+
/** Every var key the manifest knows about, in section order. */
|
|
43
|
+
export declare function allKeys(): string[];
|
|
44
|
+
/** Look up a var spec by key across all sections. */
|
|
45
|
+
export declare function findVar(key: string): VarSpec | undefined;
|
|
46
|
+
/** Keys that make up the Quick-setup subset (auth & repo + base branch). */
|
|
47
|
+
export declare const QUICK_KEYS: string[];
|
|
48
|
+
//# sourceMappingURL=manifest.d.ts.map
|