ceetrix 0.0.1 → 1.0.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/LICENSE +201 -0
- package/README.md +34 -0
- package/bin/ceetrix.js +21 -0
- package/dist/browser.d.ts +11 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +27 -0
- package/dist/browser.js.map +1 -0
- package/dist/claude.d.ts +29 -0
- package/dist/claude.d.ts.map +1 -0
- package/dist/claude.js +73 -0
- package/dist/claude.js.map +1 -0
- package/dist/config.d.ts +16 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +21 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +19 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +25 -0
- package/dist/constants.js.map +1 -0
- package/dist/git.d.ts +30 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +64 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +182 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts.d.ts +25 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +62 -0
- package/dist/prompts.js.map +1 -0
- package/dist/server.d.ts +24 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +129 -0
- package/dist/server.js.map +1 -0
- package/package.json +43 -4
- package/placeholder.js +0 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Ceetrix
|
|
2
|
+
|
|
3
|
+
Set up Ceetrix backlog management for Claude Code.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx ceetrix
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Run this command in a git repository with a GitHub remote. It will:
|
|
12
|
+
|
|
13
|
+
1. Open your browser for GitHub authentication
|
|
14
|
+
2. Install the Ceetrix GitHub App on your repository
|
|
15
|
+
3. Configure Claude Code to use the Ceetrix MCP server
|
|
16
|
+
|
|
17
|
+
## Requirements
|
|
18
|
+
|
|
19
|
+
- Node.js >= 18
|
|
20
|
+
- Claude Code CLI installed
|
|
21
|
+
- A GitHub repository
|
|
22
|
+
|
|
23
|
+
## What is Ceetrix?
|
|
24
|
+
|
|
25
|
+
Ceetrix is a backlog management system designed for AI-assisted development with Claude Code. It provides MCP (Model Context Protocol) tools that let Claude help you:
|
|
26
|
+
|
|
27
|
+
- Create and manage user stories
|
|
28
|
+
- Break down work into tasks
|
|
29
|
+
- Track progress on features and bugs
|
|
30
|
+
- Plan sprints and releases
|
|
31
|
+
|
|
32
|
+
## License
|
|
33
|
+
|
|
34
|
+
MIT
|
package/bin/ceetrix.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { main } from '../dist/index.js';
|
|
3
|
+
import whyIsNodeRunning from 'why-is-node-running';
|
|
4
|
+
|
|
5
|
+
console.log('[DEBUG] ceetrix.js: calling main()...');
|
|
6
|
+
main()
|
|
7
|
+
.then(() => {
|
|
8
|
+
console.log('[DEBUG] ceetrix.js: main() resolved successfully');
|
|
9
|
+
// @inquirer/prompts leaves stdin open - unref it so Node can exit
|
|
10
|
+
process.stdin.unref();
|
|
11
|
+
console.log('[DEBUG] stdin unref() called');
|
|
12
|
+
// Check what's keeping Node alive after 2 seconds
|
|
13
|
+
setTimeout(() => {
|
|
14
|
+
console.log('[DEBUG] 2s after main() completed - checking why Node is still running...');
|
|
15
|
+
whyIsNodeRunning();
|
|
16
|
+
}, 2000).unref();
|
|
17
|
+
})
|
|
18
|
+
.catch((err) => {
|
|
19
|
+
console.error(err.message);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser launch utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Open the system browser to the specified URL.
|
|
6
|
+
*
|
|
7
|
+
* @param url - URL to open
|
|
8
|
+
* @returns true if browser was opened, false otherwise
|
|
9
|
+
*/
|
|
10
|
+
export declare function openBrowser(url: string): Promise<boolean>;
|
|
11
|
+
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAc/D"}
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser launch utilities
|
|
3
|
+
*/
|
|
4
|
+
import open from 'open';
|
|
5
|
+
/**
|
|
6
|
+
* Open the system browser to the specified URL.
|
|
7
|
+
*
|
|
8
|
+
* @param url - URL to open
|
|
9
|
+
* @returns true if browser was opened, false otherwise
|
|
10
|
+
*/
|
|
11
|
+
export async function openBrowser(url) {
|
|
12
|
+
try {
|
|
13
|
+
console.log('[DEBUG] openBrowser: calling open()...');
|
|
14
|
+
const childProcess = await open(url);
|
|
15
|
+
console.log('[DEBUG] openBrowser: open() returned, pid:', childProcess.pid);
|
|
16
|
+
// Detach the child process so Node.js can exit cleanly
|
|
17
|
+
// without waiting for the browser to close
|
|
18
|
+
childProcess.unref();
|
|
19
|
+
console.log('[DEBUG] openBrowser: unref() called');
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
console.log('[DEBUG] openBrowser: error:', err);
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW;IAC3C,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;QACtD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,4CAA4C,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC;QAC5E,uDAAuD;QACvD,2CAA2C;QAC3C,YAAY,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
package/dist/claude.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude CLI integration
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Check if the Claude CLI is available in PATH.
|
|
6
|
+
*
|
|
7
|
+
* @returns true if claude command is available
|
|
8
|
+
*/
|
|
9
|
+
export declare function checkClaudeCli(): Promise<boolean>;
|
|
10
|
+
/**
|
|
11
|
+
* Add Ceetrix MCP server configuration to Claude Code.
|
|
12
|
+
*
|
|
13
|
+
* @param apiKey - The API key to use for authentication
|
|
14
|
+
* @throws Error if the command fails
|
|
15
|
+
*/
|
|
16
|
+
export declare function addConfig(apiKey: string): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Check if Ceetrix is already configured in Claude Code.
|
|
19
|
+
*
|
|
20
|
+
* @returns true if ceetrix server is configured
|
|
21
|
+
*/
|
|
22
|
+
export declare function checkExistingConfig(): Promise<boolean>;
|
|
23
|
+
/**
|
|
24
|
+
* Remove Ceetrix configuration from Claude Code.
|
|
25
|
+
*
|
|
26
|
+
* @throws Error if the command fails
|
|
27
|
+
*/
|
|
28
|
+
export declare function removeConfig(): Promise<void>;
|
|
29
|
+
//# sourceMappingURL=claude.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../src/claude.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH;;;;GAIG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CASvD;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB7D;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC,CAS5D;AAED;;;;GAIG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAIlD"}
|
package/dist/claude.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude CLI integration
|
|
3
|
+
*/
|
|
4
|
+
import { exec } from 'child_process';
|
|
5
|
+
import { promisify } from 'util';
|
|
6
|
+
import { getMcpServerUrl } from './constants.js';
|
|
7
|
+
const execAsync = promisify(exec);
|
|
8
|
+
/** Timeout for Claude CLI commands in milliseconds */
|
|
9
|
+
const CLAUDE_COMMAND_TIMEOUT_MS = 10000;
|
|
10
|
+
/**
|
|
11
|
+
* Check if the Claude CLI is available in PATH.
|
|
12
|
+
*
|
|
13
|
+
* @returns true if claude command is available
|
|
14
|
+
*/
|
|
15
|
+
export async function checkClaudeCli() {
|
|
16
|
+
try {
|
|
17
|
+
await execAsync('claude --version', {
|
|
18
|
+
timeout: CLAUDE_COMMAND_TIMEOUT_MS,
|
|
19
|
+
});
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Add Ceetrix MCP server configuration to Claude Code.
|
|
28
|
+
*
|
|
29
|
+
* @param apiKey - The API key to use for authentication
|
|
30
|
+
* @throws Error if the command fails
|
|
31
|
+
*/
|
|
32
|
+
export async function addConfig(apiKey) {
|
|
33
|
+
const config = {
|
|
34
|
+
type: 'http',
|
|
35
|
+
url: getMcpServerUrl(),
|
|
36
|
+
headers: {
|
|
37
|
+
'X-API-Key': apiKey,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
const configJson = JSON.stringify(config);
|
|
41
|
+
// Escape single quotes for shell
|
|
42
|
+
const escaped = configJson.replace(/'/g, "'\\''");
|
|
43
|
+
await execAsync(`claude mcp add-json ceetrix '${escaped}' --scope user`, {
|
|
44
|
+
timeout: CLAUDE_COMMAND_TIMEOUT_MS,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Check if Ceetrix is already configured in Claude Code.
|
|
49
|
+
*
|
|
50
|
+
* @returns true if ceetrix server is configured
|
|
51
|
+
*/
|
|
52
|
+
export async function checkExistingConfig() {
|
|
53
|
+
try {
|
|
54
|
+
const { stdout } = await execAsync('claude mcp list', {
|
|
55
|
+
timeout: CLAUDE_COMMAND_TIMEOUT_MS,
|
|
56
|
+
});
|
|
57
|
+
return stdout.includes('ceetrix:');
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Remove Ceetrix configuration from Claude Code.
|
|
65
|
+
*
|
|
66
|
+
* @throws Error if the command fails
|
|
67
|
+
*/
|
|
68
|
+
export async function removeConfig() {
|
|
69
|
+
await execAsync('claude mcp remove ceetrix', {
|
|
70
|
+
timeout: CLAUDE_COMMAND_TIMEOUT_MS,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../src/claude.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAElC,sDAAsD;AACtD,MAAM,yBAAyB,GAAG,KAAK,CAAC;AAExC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,kBAAkB,EAAE;YAClC,OAAO,EAAE,yBAAyB;SACnC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAc;IAC5C,MAAM,MAAM,GAAG;QACb,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE,eAAe,EAAE;QACtB,OAAO,EAAE;YACP,WAAW,EAAE,MAAM;SACpB;KACF,CAAC;IAEF,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAE1C,iCAAiC;IACjC,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAElD,MAAM,SAAS,CAAC,gCAAgC,OAAO,gBAAgB,EAAE;QACvE,OAAO,EAAE,yBAAyB;KACnC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,iBAAiB,EAAE;YACpD,OAAO,EAAE,yBAAyB;SACnC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,SAAS,CAAC,2BAA2B,EAAE;QAC3C,OAAO,EAAE,yBAAyB;KACnC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration management for existing Ceetrix setup
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Check if Ceetrix is already configured in Claude Code.
|
|
6
|
+
*
|
|
7
|
+
* @returns true if ceetrix MCP server is configured
|
|
8
|
+
*/
|
|
9
|
+
export declare function checkExistingConfig(): Promise<boolean>;
|
|
10
|
+
/**
|
|
11
|
+
* Remove existing Ceetrix configuration from Claude Code.
|
|
12
|
+
*
|
|
13
|
+
* @throws Error if removal fails
|
|
14
|
+
*/
|
|
15
|
+
export declare function removeExistingConfig(): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;GAIG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE5D;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAE1D"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration management for existing Ceetrix setup
|
|
3
|
+
*/
|
|
4
|
+
import { checkExistingConfig as checkClaudeConfig, removeConfig as removeClaudeConfig } from './claude.js';
|
|
5
|
+
/**
|
|
6
|
+
* Check if Ceetrix is already configured in Claude Code.
|
|
7
|
+
*
|
|
8
|
+
* @returns true if ceetrix MCP server is configured
|
|
9
|
+
*/
|
|
10
|
+
export async function checkExistingConfig() {
|
|
11
|
+
return checkClaudeConfig();
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Remove existing Ceetrix configuration from Claude Code.
|
|
15
|
+
*
|
|
16
|
+
* @throws Error if removal fails
|
|
17
|
+
*/
|
|
18
|
+
export async function removeExistingConfig() {
|
|
19
|
+
await removeClaudeConfig();
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,mBAAmB,IAAI,iBAAiB,EAAE,YAAY,IAAI,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAE3G;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,OAAO,iBAAiB,EAAE,CAAC;AAC7B,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,MAAM,kBAAkB,EAAE,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for ceetrix CLI
|
|
3
|
+
*
|
|
4
|
+
* Note: Functions are used for env-based values to ensure they're read at runtime,
|
|
5
|
+
* not at build time when TypeScript compiles.
|
|
6
|
+
*/
|
|
7
|
+
/** Base URL for Ceetrix API, can be overridden via CEETRIX_API_URL env var */
|
|
8
|
+
export declare function getApiBaseUrl(): string;
|
|
9
|
+
/** Setup endpoint URL */
|
|
10
|
+
export declare function getSetupUrl(): string;
|
|
11
|
+
/** Authentication timeout in milliseconds (5 minutes) */
|
|
12
|
+
export declare const AUTH_TIMEOUT_MS: number;
|
|
13
|
+
/** Default port for local callback server */
|
|
14
|
+
export declare const DEFAULT_PORT = 54321;
|
|
15
|
+
/** Ports to try for callback server if default is in use */
|
|
16
|
+
export declare const PORT_RANGE: number[];
|
|
17
|
+
/** MCP server URL for Claude Code config (Streamable HTTP transport) */
|
|
18
|
+
export declare function getMcpServerUrl(): string;
|
|
19
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,8EAA8E;AAC9E,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,yBAAyB;AACzB,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,yDAAyD;AACzD,eAAO,MAAM,eAAe,QAAgB,CAAC;AAE7C,6CAA6C;AAC7C,eAAO,MAAM,YAAY,QAAQ,CAAC;AAElC,4DAA4D;AAC5D,eAAO,MAAM,UAAU,UAAsC,CAAC;AAE9D,wEAAwE;AACxE,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for ceetrix CLI
|
|
3
|
+
*
|
|
4
|
+
* Note: Functions are used for env-based values to ensure they're read at runtime,
|
|
5
|
+
* not at build time when TypeScript compiles.
|
|
6
|
+
*/
|
|
7
|
+
/** Base URL for Ceetrix API, can be overridden via CEETRIX_API_URL env var */
|
|
8
|
+
export function getApiBaseUrl() {
|
|
9
|
+
return process.env.CEETRIX_API_URL || 'https://app.ceetrix.com';
|
|
10
|
+
}
|
|
11
|
+
/** Setup endpoint URL */
|
|
12
|
+
export function getSetupUrl() {
|
|
13
|
+
return `${getApiBaseUrl()}/setup`;
|
|
14
|
+
}
|
|
15
|
+
/** Authentication timeout in milliseconds (5 minutes) */
|
|
16
|
+
export const AUTH_TIMEOUT_MS = 5 * 60 * 1000;
|
|
17
|
+
/** Default port for local callback server */
|
|
18
|
+
export const DEFAULT_PORT = 54321;
|
|
19
|
+
/** Ports to try for callback server if default is in use */
|
|
20
|
+
export const PORT_RANGE = [54321, 54322, 54323, 54324, 54325];
|
|
21
|
+
/** MCP server URL for Claude Code config (Streamable HTTP transport) */
|
|
22
|
+
export function getMcpServerUrl() {
|
|
23
|
+
return process.env.CEETRIX_MCP_URL || 'https://api.ceetrix.com/sse';
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,8EAA8E;AAC9E,MAAM,UAAU,aAAa;IAC3B,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,yBAAyB,CAAC;AAClE,CAAC;AAED,yBAAyB;AACzB,MAAM,UAAU,WAAW;IACzB,OAAO,GAAG,aAAa,EAAE,QAAQ,CAAC;AACpC,CAAC;AAED,yDAAyD;AACzD,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAE7C,6CAA6C;AAC7C,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC;AAElC,4DAA4D;AAC5D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAE9D,wEAAwE;AACxE,MAAM,UAAU,eAAe;IAC7B,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,6BAA6B,CAAC;AACtE,CAAC"}
|
package/dist/git.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git remote detection utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Result of git remote detection
|
|
6
|
+
*/
|
|
7
|
+
export type GitDetectionResult = {
|
|
8
|
+
status: 'detected';
|
|
9
|
+
repo: string;
|
|
10
|
+
} | {
|
|
11
|
+
status: 'no-git-repo';
|
|
12
|
+
} | {
|
|
13
|
+
status: 'no-remote';
|
|
14
|
+
} | {
|
|
15
|
+
status: 'not-github';
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Detect the GitHub repository from git remote origin.
|
|
19
|
+
* @returns Detection result with status and repo if found
|
|
20
|
+
*/
|
|
21
|
+
export declare function detectGitRemote(): Promise<GitDetectionResult>;
|
|
22
|
+
/**
|
|
23
|
+
* Parse a git URL to extract owner/repo.
|
|
24
|
+
* Supports SSH and HTTPS formats.
|
|
25
|
+
*
|
|
26
|
+
* @param url - Git remote URL
|
|
27
|
+
* @returns owner/repo string or null if not a valid GitHub URL
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseGitUrl(url: string): string | null;
|
|
30
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,GACzB;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,GACvB;IAAE,MAAM,EAAE,YAAY,CAAA;CAAE,CAAC;AAE7B;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,kBAAkB,CAAC,CA4BnE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBtD"}
|
package/dist/git.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git remote detection utilities
|
|
3
|
+
*/
|
|
4
|
+
import { exec } from 'child_process';
|
|
5
|
+
import { promisify } from 'util';
|
|
6
|
+
const execAsync = promisify(exec);
|
|
7
|
+
/** Timeout for git commands in milliseconds */
|
|
8
|
+
const GIT_COMMAND_TIMEOUT_MS = 5000;
|
|
9
|
+
/**
|
|
10
|
+
* Detect the GitHub repository from git remote origin.
|
|
11
|
+
* @returns Detection result with status and repo if found
|
|
12
|
+
*/
|
|
13
|
+
export async function detectGitRemote() {
|
|
14
|
+
// First check if we're in a git repository
|
|
15
|
+
try {
|
|
16
|
+
await execAsync('git rev-parse --is-inside-work-tree', {
|
|
17
|
+
timeout: GIT_COMMAND_TIMEOUT_MS,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return { status: 'no-git-repo' };
|
|
22
|
+
}
|
|
23
|
+
// Check for remote origin
|
|
24
|
+
let remoteUrl;
|
|
25
|
+
try {
|
|
26
|
+
const { stdout } = await execAsync('git config --get remote.origin.url', {
|
|
27
|
+
timeout: GIT_COMMAND_TIMEOUT_MS,
|
|
28
|
+
});
|
|
29
|
+
remoteUrl = stdout.trim();
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return { status: 'no-remote' };
|
|
33
|
+
}
|
|
34
|
+
// Parse the URL
|
|
35
|
+
const repo = parseGitUrl(remoteUrl);
|
|
36
|
+
if (!repo) {
|
|
37
|
+
return { status: 'not-github' };
|
|
38
|
+
}
|
|
39
|
+
return { status: 'detected', repo };
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Parse a git URL to extract owner/repo.
|
|
43
|
+
* Supports SSH and HTTPS formats.
|
|
44
|
+
*
|
|
45
|
+
* @param url - Git remote URL
|
|
46
|
+
* @returns owner/repo string or null if not a valid GitHub URL
|
|
47
|
+
*/
|
|
48
|
+
export function parseGitUrl(url) {
|
|
49
|
+
if (!url) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
// SSH format: git@github.com:owner/repo.git
|
|
53
|
+
const sshMatch = url.match(/git@github\.com:([^/]+)\/([^/.]+)/);
|
|
54
|
+
if (sshMatch) {
|
|
55
|
+
return `${sshMatch[1]}/${sshMatch[2]}`;
|
|
56
|
+
}
|
|
57
|
+
// HTTPS format: https://github.com/owner/repo.git
|
|
58
|
+
const httpsMatch = url.match(/github\.com\/([^/]+)\/([^/.]+)/);
|
|
59
|
+
if (httpsMatch) {
|
|
60
|
+
return `${httpsMatch[1]}/${httpsMatch[2]}`;
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=git.js.map
|
package/dist/git.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAEjC,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAElC,+CAA+C;AAC/C,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAWpC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,2CAA2C;IAC3C,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,qCAAqC,EAAE;YACrD,OAAO,EAAE,sBAAsB;SAChC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IACnC,CAAC;IAED,0BAA0B;IAC1B,IAAI,SAAiB,CAAC;IACtB,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,oCAAoC,EAAE;YACvE,OAAO,EAAE,sBAAsB;SAChC,CAAC,CAAC;QACH,SAAS,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACjC,CAAC;IAED,gBAAgB;IAChB,MAAM,IAAI,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;IACpC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAClC,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;AACtC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,IAAI,CAAC;IACd,CAAC;IAED,4CAA4C;IAC5C,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAChE,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACzC,CAAC;IAED,kDAAkD;IAClD,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAC/D,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7C,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAmD1C"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ceetrix CLI - Set up Ceetrix backlog management for Claude Code
|
|
3
|
+
*/
|
|
4
|
+
import { detectGitRemote } from './git.js';
|
|
5
|
+
import { checkExistingConfig, removeExistingConfig } from './config.js';
|
|
6
|
+
import { startCallbackServer } from './server.js';
|
|
7
|
+
import { openBrowser } from './browser.js';
|
|
8
|
+
import { promptForRepo, promptExistingConfig } from './prompts.js';
|
|
9
|
+
import { checkClaudeCli, addConfig } from './claude.js';
|
|
10
|
+
import { getSetupUrl, AUTH_TIMEOUT_MS } from './constants.js';
|
|
11
|
+
/**
|
|
12
|
+
* Main CLI entry point
|
|
13
|
+
*/
|
|
14
|
+
export async function main() {
|
|
15
|
+
console.log('[DEBUG] main() started');
|
|
16
|
+
console.log('\nCeetrix Setup');
|
|
17
|
+
console.log('─────────────\n');
|
|
18
|
+
// Check Claude CLI is available
|
|
19
|
+
const claudeAvailable = await checkClaudeCli();
|
|
20
|
+
if (!claudeAvailable) {
|
|
21
|
+
console.error('✗ Claude Code CLI not found\n');
|
|
22
|
+
console.error('Install Claude Code first:');
|
|
23
|
+
console.error('https://claude.ai/download\n');
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
// Check if already configured
|
|
27
|
+
const existingConfig = await checkExistingConfig();
|
|
28
|
+
if (existingConfig) {
|
|
29
|
+
const action = await handleExistingConfig();
|
|
30
|
+
if (action === 'cancel' || action === 'done') {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
// For 'continue', proceed with normal flow
|
|
34
|
+
}
|
|
35
|
+
// Detect or prompt for repo
|
|
36
|
+
const detection = await detectGitRemote();
|
|
37
|
+
let repo;
|
|
38
|
+
if (detection.status === 'detected') {
|
|
39
|
+
console.log(`Detected repository: github.com/${detection.repo}\n`);
|
|
40
|
+
repo = detection.repo;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// Show appropriate message based on detection status
|
|
44
|
+
switch (detection.status) {
|
|
45
|
+
case 'no-git-repo':
|
|
46
|
+
console.log('Not inside a git repository.\n');
|
|
47
|
+
break;
|
|
48
|
+
case 'no-remote':
|
|
49
|
+
console.log('Git repository has no remote origin configured.\n');
|
|
50
|
+
break;
|
|
51
|
+
case 'not-github':
|
|
52
|
+
console.log('Remote origin is not a GitHub repository.\n');
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
repo = await promptForRepo();
|
|
56
|
+
}
|
|
57
|
+
// Run the setup flow
|
|
58
|
+
console.log('[DEBUG] Calling runSetupFlow...');
|
|
59
|
+
await runSetupFlow(repo);
|
|
60
|
+
console.log('[DEBUG] runSetupFlow completed, main() returning');
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Handle case when Ceetrix is already configured.
|
|
64
|
+
*
|
|
65
|
+
* @returns Action taken: 'cancel', 'done', or 'continue'
|
|
66
|
+
*/
|
|
67
|
+
async function handleExistingConfig() {
|
|
68
|
+
const action = await promptExistingConfig();
|
|
69
|
+
switch (action) {
|
|
70
|
+
case 'cancel':
|
|
71
|
+
return 'cancel';
|
|
72
|
+
case 'remove':
|
|
73
|
+
console.log('Removing Ceetrix configuration...');
|
|
74
|
+
try {
|
|
75
|
+
await removeExistingConfig();
|
|
76
|
+
console.log('✓ Ceetrix removed\n');
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
console.error('✗ Failed to remove configuration\n');
|
|
80
|
+
throw err;
|
|
81
|
+
}
|
|
82
|
+
return 'done';
|
|
83
|
+
case 'reauth':
|
|
84
|
+
// Continue with normal flow to get new API key
|
|
85
|
+
console.log('Re-authenticating...\n');
|
|
86
|
+
return 'continue';
|
|
87
|
+
case 'add-repo':
|
|
88
|
+
// Continue with normal flow
|
|
89
|
+
console.log('Adding repository...\n');
|
|
90
|
+
return 'continue';
|
|
91
|
+
default:
|
|
92
|
+
return 'cancel';
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Run the OAuth setup flow.
|
|
97
|
+
*
|
|
98
|
+
* @param repo - The repository to set up (owner/repo)
|
|
99
|
+
*/
|
|
100
|
+
async function runSetupFlow(repo) {
|
|
101
|
+
// Start callback server
|
|
102
|
+
const { port, waitForCallback, close } = await startCallbackServer();
|
|
103
|
+
try {
|
|
104
|
+
// Build setup URL
|
|
105
|
+
const callbackUrl = `http://localhost:${port}/callback`;
|
|
106
|
+
const setupUrl = `${getSetupUrl()}?callback=${encodeURIComponent(callbackUrl)}&repo=${encodeURIComponent(repo)}`;
|
|
107
|
+
// Open browser
|
|
108
|
+
const opened = await openBrowser(setupUrl);
|
|
109
|
+
if (!opened) {
|
|
110
|
+
console.log('Could not open browser automatically.');
|
|
111
|
+
console.log('Please open this URL manually:\n');
|
|
112
|
+
console.log(` ${setupUrl}\n`);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
console.log('Opening browser for GitHub authentication...');
|
|
116
|
+
}
|
|
117
|
+
console.log('Waiting for authentication...\n');
|
|
118
|
+
// Wait for callback with timeout
|
|
119
|
+
const authTimeout = createCancellableTimeout(AUTH_TIMEOUT_MS);
|
|
120
|
+
const result = await Promise.race([
|
|
121
|
+
waitForCallback(),
|
|
122
|
+
authTimeout.promise,
|
|
123
|
+
]);
|
|
124
|
+
// Cancel the timeout to allow Node.js to exit cleanly
|
|
125
|
+
authTimeout.cancel();
|
|
126
|
+
if (!result) {
|
|
127
|
+
console.error('✗ Authentication timed out\n');
|
|
128
|
+
console.error('Run `npx ceetrix` again to retry.\n');
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
// Show success
|
|
132
|
+
console.log(`✓ Authenticated as @${result.username}`);
|
|
133
|
+
if (result.repos.length > 0) {
|
|
134
|
+
console.log(`✓ Access granted to: ${result.repos.join(', ')}\n`);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
console.log('');
|
|
138
|
+
}
|
|
139
|
+
// Add to Claude config
|
|
140
|
+
console.log('Adding Ceetrix to Claude Code...');
|
|
141
|
+
await addConfig(result.apiKey);
|
|
142
|
+
console.log('✓ Configuration added\n');
|
|
143
|
+
// Show restart notice
|
|
144
|
+
printRestartNotice();
|
|
145
|
+
console.log('[DEBUG] About to close server...');
|
|
146
|
+
}
|
|
147
|
+
finally {
|
|
148
|
+
console.log('[DEBUG] In finally block, calling close()...');
|
|
149
|
+
close();
|
|
150
|
+
console.log('[DEBUG] Server closed');
|
|
151
|
+
}
|
|
152
|
+
console.log('[DEBUG] runSetupFlow() returning');
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Create a cancellable timeout promise.
|
|
156
|
+
*
|
|
157
|
+
* @param ms - Timeout in milliseconds
|
|
158
|
+
* @returns Object with promise and cancel function
|
|
159
|
+
*/
|
|
160
|
+
function createCancellableTimeout(ms) {
|
|
161
|
+
let timeoutId;
|
|
162
|
+
const promise = new Promise((resolve) => {
|
|
163
|
+
timeoutId = setTimeout(() => resolve(null), ms);
|
|
164
|
+
});
|
|
165
|
+
return {
|
|
166
|
+
promise,
|
|
167
|
+
cancel: () => clearTimeout(timeoutId),
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Print the restart notice with instructions.
|
|
172
|
+
*/
|
|
173
|
+
function printRestartNotice() {
|
|
174
|
+
console.log('┌─────────────────────────────────────────────────────────────────┐');
|
|
175
|
+
console.log('│ ⚠️ Restart Claude Code to activate Ceetrix │');
|
|
176
|
+
console.log('│ │');
|
|
177
|
+
console.log('│ Claude Code does not auto-detect new MCP servers. │');
|
|
178
|
+
console.log('│ Quit and reopen Claude Code, then describe a feature you │');
|
|
179
|
+
console.log('│ want to build and ask Claude to "create a story for it". │');
|
|
180
|
+
console.log('└─────────────────────────────────────────────────────────────────┘\n');
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive prompts for user input
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Prompt user for repository in owner/repo format.
|
|
6
|
+
*
|
|
7
|
+
* @returns The repository string (e.g., "owner/repo")
|
|
8
|
+
*/
|
|
9
|
+
export declare function promptForRepo(): Promise<string>;
|
|
10
|
+
/** Actions available when Ceetrix is already configured */
|
|
11
|
+
export type ExistingConfigAction = 'add-repo' | 'reauth' | 'remove' | 'cancel';
|
|
12
|
+
/**
|
|
13
|
+
* Prompt user to choose an action when Ceetrix is already configured.
|
|
14
|
+
*
|
|
15
|
+
* @returns The selected action
|
|
16
|
+
*/
|
|
17
|
+
export declare function promptExistingConfig(): Promise<ExistingConfigAction>;
|
|
18
|
+
/**
|
|
19
|
+
* Prompt user to confirm an action.
|
|
20
|
+
*
|
|
21
|
+
* @param message - The confirmation message
|
|
22
|
+
* @returns true if user confirms
|
|
23
|
+
*/
|
|
24
|
+
export declare function promptConfirm(message: string): Promise<boolean>;
|
|
25
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;GAIG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CAkBrD;AAED,2DAA2D;AAC3D,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/E;;;;GAIG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAW1E;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CASrE"}
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive prompts for user input
|
|
3
|
+
*/
|
|
4
|
+
import { input, select } from '@inquirer/prompts';
|
|
5
|
+
/**
|
|
6
|
+
* Prompt user for repository in owner/repo format.
|
|
7
|
+
*
|
|
8
|
+
* @returns The repository string (e.g., "owner/repo")
|
|
9
|
+
*/
|
|
10
|
+
export async function promptForRepo() {
|
|
11
|
+
const repo = await input({
|
|
12
|
+
message: 'Enter repository (owner/repo):',
|
|
13
|
+
validate: (value) => {
|
|
14
|
+
if (!value.includes('/')) {
|
|
15
|
+
return 'Format: owner/repo';
|
|
16
|
+
}
|
|
17
|
+
if (value.split('/').length !== 2) {
|
|
18
|
+
return 'Format: owner/repo';
|
|
19
|
+
}
|
|
20
|
+
const [owner, name] = value.split('/');
|
|
21
|
+
if (!owner || !name) {
|
|
22
|
+
return 'Format: owner/repo';
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
return repo;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Prompt user to choose an action when Ceetrix is already configured.
|
|
31
|
+
*
|
|
32
|
+
* @returns The selected action
|
|
33
|
+
*/
|
|
34
|
+
export async function promptExistingConfig() {
|
|
35
|
+
const action = await select({
|
|
36
|
+
message: 'Ceetrix is already configured. What would you like to do?',
|
|
37
|
+
choices: [
|
|
38
|
+
{ name: 'Add another repository', value: 'add-repo' },
|
|
39
|
+
{ name: 'Re-authenticate (get new API key)', value: 'reauth' },
|
|
40
|
+
{ name: 'Remove Ceetrix', value: 'remove' },
|
|
41
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
42
|
+
],
|
|
43
|
+
});
|
|
44
|
+
return action;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Prompt user to confirm an action.
|
|
48
|
+
*
|
|
49
|
+
* @param message - The confirmation message
|
|
50
|
+
* @returns true if user confirms
|
|
51
|
+
*/
|
|
52
|
+
export async function promptConfirm(message) {
|
|
53
|
+
const response = await select({
|
|
54
|
+
message,
|
|
55
|
+
choices: [
|
|
56
|
+
{ name: 'Yes', value: true },
|
|
57
|
+
{ name: 'No', value: false },
|
|
58
|
+
],
|
|
59
|
+
});
|
|
60
|
+
return response;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAElD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC;QACvB,OAAO,EAAE,gCAAgC;QACzC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;YAClB,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzB,OAAO,oBAAoB,CAAC;YAC9B,CAAC;YACD,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAClC,OAAO,oBAAoB,CAAC;YAC9B,CAAC;YACD,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACvC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;gBACpB,OAAO,oBAAoB,CAAC;YAC9B,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC;AAKD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC;QAC1B,OAAO,EAAE,2DAA2D;QACpE,OAAO,EAAE;YACP,EAAE,IAAI,EAAE,wBAAwB,EAAE,KAAK,EAAE,UAAmB,EAAE;YAC9D,EAAE,IAAI,EAAE,mCAAmC,EAAE,KAAK,EAAE,QAAiB,EAAE;YACvE,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,QAAiB,EAAE;YACpD,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAiB,EAAE;SAC7C;KACF,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAe;IACjD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC;QAC5B,OAAO;QACP,OAAO,EAAE;YACP,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE;YAC5B,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE;SAC7B;KACF,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local callback server for receiving OAuth results
|
|
3
|
+
*/
|
|
4
|
+
/** Result received from OAuth callback */
|
|
5
|
+
export interface CallbackResult {
|
|
6
|
+
apiKey: string;
|
|
7
|
+
username: string;
|
|
8
|
+
repos: string[];
|
|
9
|
+
}
|
|
10
|
+
/** Callback server interface */
|
|
11
|
+
export interface CallbackServer {
|
|
12
|
+
port: number;
|
|
13
|
+
waitForCallback: () => Promise<CallbackResult>;
|
|
14
|
+
close: () => void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Start a local HTTP server to receive the OAuth callback.
|
|
18
|
+
* Tries ports in PORT_RANGE until one is available.
|
|
19
|
+
*
|
|
20
|
+
* @returns Server interface with port, waitForCallback promise, and close function
|
|
21
|
+
* @throws Error if no ports are available
|
|
22
|
+
*/
|
|
23
|
+
export declare function startCallbackServer(): Promise<CallbackServer>;
|
|
24
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,0CAA0C;AAC1C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,gCAAgC;AAChC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;IAC/C,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,cAAc,CAAC,CA2BnE"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local callback server for receiving OAuth results
|
|
3
|
+
*/
|
|
4
|
+
import { createServer } from 'http';
|
|
5
|
+
import { PORT_RANGE } from './constants.js';
|
|
6
|
+
/**
|
|
7
|
+
* Start a local HTTP server to receive the OAuth callback.
|
|
8
|
+
* Tries ports in PORT_RANGE until one is available.
|
|
9
|
+
*
|
|
10
|
+
* @returns Server interface with port, waitForCallback promise, and close function
|
|
11
|
+
* @throws Error if no ports are available
|
|
12
|
+
*/
|
|
13
|
+
export async function startCallbackServer() {
|
|
14
|
+
let resolveCallback;
|
|
15
|
+
const callbackPromise = new Promise((resolve) => {
|
|
16
|
+
resolveCallback = resolve;
|
|
17
|
+
});
|
|
18
|
+
const server = createServer((req, res) => {
|
|
19
|
+
handleRequest(req, res, resolveCallback);
|
|
20
|
+
});
|
|
21
|
+
const port = await findAvailablePort(server);
|
|
22
|
+
return {
|
|
23
|
+
port,
|
|
24
|
+
waitForCallback: () => callbackPromise,
|
|
25
|
+
close: () => {
|
|
26
|
+
console.log('[DEBUG] server.close() called');
|
|
27
|
+
// closeAllConnections() ensures all keep-alive connections are terminated
|
|
28
|
+
// so Node.js can exit cleanly (available in Node 18.2+)
|
|
29
|
+
server.closeAllConnections();
|
|
30
|
+
console.log('[DEBUG] closeAllConnections() done');
|
|
31
|
+
server.close(() => {
|
|
32
|
+
console.log('[DEBUG] server.close() callback - server fully closed');
|
|
33
|
+
});
|
|
34
|
+
console.log('[DEBUG] server.close() initiated');
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Handle incoming HTTP requests to the callback server.
|
|
40
|
+
*/
|
|
41
|
+
function handleRequest(req, res, resolveCallback) {
|
|
42
|
+
const reqUrl = req.url || '';
|
|
43
|
+
if (!reqUrl.startsWith('/callback')) {
|
|
44
|
+
res.writeHead(404);
|
|
45
|
+
res.end();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const url = new URL(reqUrl, 'http://localhost');
|
|
49
|
+
const apiKey = url.searchParams.get('api_key');
|
|
50
|
+
const username = url.searchParams.get('username');
|
|
51
|
+
const reposParam = url.searchParams.get('repos');
|
|
52
|
+
const repos = reposParam ? reposParam.split(',').filter(Boolean) : [];
|
|
53
|
+
if (!apiKey || !username) {
|
|
54
|
+
res.writeHead(400, { 'Content-Type': 'text/plain' });
|
|
55
|
+
res.end('Missing required parameters');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
// Return success page
|
|
59
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
60
|
+
res.end(getSuccessHtml());
|
|
61
|
+
resolveCallback({ apiKey, username, repos });
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* HTML page shown in browser after successful callback.
|
|
65
|
+
*/
|
|
66
|
+
function getSuccessHtml() {
|
|
67
|
+
return `<!DOCTYPE html>
|
|
68
|
+
<html>
|
|
69
|
+
<head>
|
|
70
|
+
<title>Ceetrix Setup</title>
|
|
71
|
+
<style>
|
|
72
|
+
body {
|
|
73
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
74
|
+
text-align: center;
|
|
75
|
+
padding: 3rem;
|
|
76
|
+
background: #f8f9fa;
|
|
77
|
+
}
|
|
78
|
+
.container {
|
|
79
|
+
max-width: 400px;
|
|
80
|
+
margin: 0 auto;
|
|
81
|
+
background: white;
|
|
82
|
+
padding: 2rem;
|
|
83
|
+
border-radius: 8px;
|
|
84
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
85
|
+
}
|
|
86
|
+
h1 { color: #22c55e; margin-bottom: 1rem; }
|
|
87
|
+
p { color: #666; }
|
|
88
|
+
</style>
|
|
89
|
+
</head>
|
|
90
|
+
<body>
|
|
91
|
+
<div class="container">
|
|
92
|
+
<h1>Setup complete!</h1>
|
|
93
|
+
<p>Return to your terminal.</p>
|
|
94
|
+
<p style="color: #999;">You can close this tab.</p>
|
|
95
|
+
</div>
|
|
96
|
+
</body>
|
|
97
|
+
</html>`;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Try to bind server to ports in PORT_RANGE until one succeeds.
|
|
101
|
+
*
|
|
102
|
+
* @param server - HTTP server instance
|
|
103
|
+
* @returns The port that was successfully bound
|
|
104
|
+
* @throws Error if all ports are in use
|
|
105
|
+
*/
|
|
106
|
+
async function findAvailablePort(server) {
|
|
107
|
+
for (const port of PORT_RANGE) {
|
|
108
|
+
try {
|
|
109
|
+
await new Promise((resolve, reject) => {
|
|
110
|
+
server.once('error', reject);
|
|
111
|
+
server.listen(port, '127.0.0.1', () => {
|
|
112
|
+
server.removeListener('error', reject);
|
|
113
|
+
resolve();
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
return port;
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
const error = err;
|
|
120
|
+
if (error.code !== 'EADDRINUSE') {
|
|
121
|
+
throw err;
|
|
122
|
+
}
|
|
123
|
+
// Port in use, try next
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
throw new Error(`No available ports. Tried: ${PORT_RANGE.join(', ')}. ` +
|
|
127
|
+
'Close other applications using these ports and try again.');
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,46 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ceetrix",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "Ceetrix
|
|
5
|
-
"bin": {
|
|
6
|
-
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Set up Ceetrix backlog management for Claude Code",
|
|
5
|
+
"bin": {
|
|
6
|
+
"ceetrix": "./bin/ceetrix.js"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=18.0.0"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"dev": "tsc --watch",
|
|
15
|
+
"test": "vitest",
|
|
16
|
+
"test:run": "vitest run",
|
|
17
|
+
"lint": "eslint src tests",
|
|
18
|
+
"prepublishOnly": "npm run build"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@inquirer/prompts": "^7.0.0",
|
|
22
|
+
"open": "^10.0.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "^20.0.0",
|
|
26
|
+
"typescript": "^5.0.0",
|
|
27
|
+
"vitest": "^2.0.0",
|
|
28
|
+
"why-is-node-running": "^3.2.2"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"bin",
|
|
32
|
+
"dist"
|
|
33
|
+
],
|
|
34
|
+
"keywords": [
|
|
35
|
+
"ceetrix",
|
|
36
|
+
"claude",
|
|
37
|
+
"claude-code",
|
|
38
|
+
"mcp",
|
|
39
|
+
"backlog"
|
|
40
|
+
],
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/ceetrixai/ceetrix.git"
|
|
45
|
+
}
|
|
7
46
|
}
|
package/placeholder.js
DELETED