moicle 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/README.md +201 -0
- package/assets/agents/developers/flutter-mobile-dev.md +69 -0
- package/assets/agents/developers/go-backend-dev.md +57 -0
- package/assets/agents/developers/laravel-backend-dev.md +123 -0
- package/assets/agents/developers/react-frontend-dev.md +69 -0
- package/assets/agents/developers/remix-fullstack-dev.md +69 -0
- package/assets/agents/utilities/api-designer.md +76 -0
- package/assets/agents/utilities/clean-architect.md +83 -0
- package/assets/agents/utilities/code-reviewer.md +76 -0
- package/assets/agents/utilities/db-designer.md +68 -0
- package/assets/agents/utilities/devops.md +71 -0
- package/assets/agents/utilities/docs-writer.md +75 -0
- package/assets/agents/utilities/perf-optimizer.md +87 -0
- package/assets/agents/utilities/refactor.md +173 -0
- package/assets/agents/utilities/security-audit.md +203 -0
- package/assets/agents/utilities/test-writer.md +139 -0
- package/assets/architecture/clean-architecture.md +143 -0
- package/assets/architecture/flutter-mobile.md +304 -0
- package/assets/architecture/go-backend.md +217 -0
- package/assets/architecture/laravel-backend.md +303 -0
- package/assets/architecture/monorepo.md +162 -0
- package/assets/architecture/react-frontend.md +268 -0
- package/assets/architecture/remix-fullstack.md +272 -0
- package/assets/commands/bootstrap.md +98 -0
- package/assets/commands/brainstorm.md +440 -0
- package/assets/skills/feature-workflow/SKILL.md +298 -0
- package/assets/skills/hotfix-workflow/SKILL.md +368 -0
- package/assets/templates/flutter/CLAUDE.md +454 -0
- package/assets/templates/go-gin/CLAUDE.md +244 -0
- package/assets/templates/monorepo/CLAUDE.md +362 -0
- package/assets/templates/react-vite/CLAUDE.md +304 -0
- package/assets/templates/remix/CLAUDE.md +304 -0
- package/bin/cli.js +76 -0
- package/dist/commands/disable.d.ts +3 -0
- package/dist/commands/disable.d.ts.map +1 -0
- package/dist/commands/disable.js +188 -0
- package/dist/commands/disable.js.map +1 -0
- package/dist/commands/enable.d.ts +3 -0
- package/dist/commands/enable.d.ts.map +1 -0
- package/dist/commands/enable.js +191 -0
- package/dist/commands/enable.js.map +1 -0
- package/dist/commands/install.d.ts +3 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +290 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/list.d.ts +3 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +75 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/postinstall.d.ts +2 -0
- package/dist/commands/postinstall.d.ts.map +1 -0
- package/dist/commands/postinstall.js +25 -0
- package/dist/commands/postinstall.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +118 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/uninstall.d.ts +3 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +178 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +47 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/config.d.ts +13 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +95 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/symlink.d.ts +24 -0
- package/dist/utils/symlink.d.ts.map +1 -0
- package/dist/utils/symlink.js +313 -0
- package/dist/utils/symlink.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# CLAUDE.md - Remix Fullstack Template
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
|
|
5
|
+
Fullstack application built with:
|
|
6
|
+
- **Remix 2** - Fullstack React framework
|
|
7
|
+
- **TypeScript** - Type safety
|
|
8
|
+
- **Tailwind CSS 4** - Utility-first CSS
|
|
9
|
+
- **Prisma** - Database ORM
|
|
10
|
+
- **shadcn/ui** - UI component library
|
|
11
|
+
|
|
12
|
+
## Quick Start
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# Install dependencies
|
|
16
|
+
pnpm install
|
|
17
|
+
|
|
18
|
+
# Setup database
|
|
19
|
+
pnpm db:push
|
|
20
|
+
|
|
21
|
+
# Run development server
|
|
22
|
+
pnpm dev
|
|
23
|
+
|
|
24
|
+
# Build for production
|
|
25
|
+
pnpm build
|
|
26
|
+
|
|
27
|
+
# Run production server
|
|
28
|
+
pnpm start
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Project Structure
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
{project_name}/
|
|
35
|
+
├── app/
|
|
36
|
+
│ ├── components/ # Shared components
|
|
37
|
+
│ │ ├── ui/ # shadcn/ui components
|
|
38
|
+
│ │ └── forms/ # Form components
|
|
39
|
+
│ ├── lib/
|
|
40
|
+
│ │ ├── db.server.ts # Prisma client
|
|
41
|
+
│ │ ├── session.server.ts # Session management
|
|
42
|
+
│ │ └── utils.ts # Utility functions
|
|
43
|
+
│ ├── models/ # Data access layer
|
|
44
|
+
│ │ └── {entity}.server.ts
|
|
45
|
+
│ ├── routes/
|
|
46
|
+
│ │ ├── _index.tsx # Home page
|
|
47
|
+
│ │ ├── _auth.tsx # Auth layout
|
|
48
|
+
│ │ ├── _auth.login.tsx # Login page
|
|
49
|
+
│ │ ├── _app.tsx # App layout (protected)
|
|
50
|
+
│ │ ├── _app.{resource}.tsx # Resource list
|
|
51
|
+
│ │ ├── _app.{resource}.$id.tsx
|
|
52
|
+
│ │ └── api.{endpoint}.ts # API routes
|
|
53
|
+
│ ├── styles/
|
|
54
|
+
│ │ └── tailwind.css
|
|
55
|
+
│ ├── entry.client.tsx
|
|
56
|
+
│ ├── entry.server.tsx
|
|
57
|
+
│ └── root.tsx
|
|
58
|
+
├── prisma/
|
|
59
|
+
│ └── schema.prisma
|
|
60
|
+
├── public/
|
|
61
|
+
├── .env
|
|
62
|
+
├── remix.config.js
|
|
63
|
+
└── package.json
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Key Patterns and Conventions
|
|
67
|
+
|
|
68
|
+
### File Naming
|
|
69
|
+
- Route files use dot notation: `_app.users.$id.tsx`
|
|
70
|
+
- Server-only files use `.server.ts` suffix
|
|
71
|
+
- Client-only files use `.client.ts` suffix
|
|
72
|
+
|
|
73
|
+
### Route Conventions
|
|
74
|
+
- `_layout.tsx` - Layout route (underscore prefix)
|
|
75
|
+
- `$param.tsx` - Dynamic parameter
|
|
76
|
+
- `_.tsx` - Pathless layout
|
|
77
|
+
- `[.]sitemap.xml.tsx` - Escape special characters
|
|
78
|
+
|
|
79
|
+
### Loader Pattern (Server-side data fetching)
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
// routes/_app.users.tsx
|
|
83
|
+
import { json, type LoaderFunctionArgs } from '@remix-run/node';
|
|
84
|
+
import { useLoaderData } from '@remix-run/react';
|
|
85
|
+
import { requireAuth } from '~/lib/session.server';
|
|
86
|
+
import { getUsers } from '~/models/user.server';
|
|
87
|
+
|
|
88
|
+
export async function loader({ request }: LoaderFunctionArgs) {
|
|
89
|
+
await requireAuth(request);
|
|
90
|
+
|
|
91
|
+
const url = new URL(request.url);
|
|
92
|
+
const page = parseInt(url.searchParams.get('page') ?? '1');
|
|
93
|
+
const search = url.searchParams.get('search') ?? '';
|
|
94
|
+
|
|
95
|
+
const { users, total } = await getUsers({ page, search });
|
|
96
|
+
|
|
97
|
+
return json({ users, total, page });
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export default function UsersPage() {
|
|
101
|
+
const { users, total, page } = useLoaderData<typeof loader>();
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<div>
|
|
105
|
+
<UserTable users={users} />
|
|
106
|
+
<Pagination total={total} currentPage={page} />
|
|
107
|
+
</div>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Action Pattern (Form submissions)
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
// routes/_app.users.new.tsx
|
|
116
|
+
import { redirect, type ActionFunctionArgs } from '@remix-run/node';
|
|
117
|
+
import { Form, useActionData } from '@remix-run/react';
|
|
118
|
+
import { createUser } from '~/models/user.server';
|
|
119
|
+
|
|
120
|
+
export async function action({ request }: ActionFunctionArgs) {
|
|
121
|
+
const formData = await request.formData();
|
|
122
|
+
const name = formData.get('name') as string;
|
|
123
|
+
const email = formData.get('email') as string;
|
|
124
|
+
|
|
125
|
+
const errors: Record<string, string> = {};
|
|
126
|
+
if (!name) errors.name = 'Name is required';
|
|
127
|
+
if (!email) errors.email = 'Email is required';
|
|
128
|
+
|
|
129
|
+
if (Object.keys(errors).length > 0) {
|
|
130
|
+
return json({ errors }, { status: 400 });
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
await createUser({ name, email });
|
|
134
|
+
return redirect('/users');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export default function NewUserPage() {
|
|
138
|
+
const actionData = useActionData<typeof action>();
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
<Form method="post">
|
|
142
|
+
<Input name="name" error={actionData?.errors?.name} />
|
|
143
|
+
<Input name="email" error={actionData?.errors?.email} />
|
|
144
|
+
<Button type="submit">Create</Button>
|
|
145
|
+
</Form>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Model Pattern (Data access layer)
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
// models/user.server.ts
|
|
154
|
+
import { db } from '~/lib/db.server';
|
|
155
|
+
|
|
156
|
+
export async function getUsers({ page = 1, limit = 10, search = '' }) {
|
|
157
|
+
const where = search
|
|
158
|
+
? { OR: [{ name: { contains: search } }, { email: { contains: search } }] }
|
|
159
|
+
: {};
|
|
160
|
+
|
|
161
|
+
const [users, total] = await Promise.all([
|
|
162
|
+
db.user.findMany({
|
|
163
|
+
where,
|
|
164
|
+
skip: (page - 1) * limit,
|
|
165
|
+
take: limit,
|
|
166
|
+
orderBy: { createdAt: 'desc' },
|
|
167
|
+
}),
|
|
168
|
+
db.user.count({ where }),
|
|
169
|
+
]);
|
|
170
|
+
|
|
171
|
+
return { users, total };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export async function getUserById(id: string) {
|
|
175
|
+
return db.user.findUnique({ where: { id } });
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export async function createUser(data: { name: string; email: string }) {
|
|
179
|
+
return db.user.create({ data });
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Session Management
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
// lib/session.server.ts
|
|
187
|
+
import { createCookieSessionStorage, redirect } from '@remix-run/node';
|
|
188
|
+
|
|
189
|
+
const sessionStorage = createCookieSessionStorage({
|
|
190
|
+
cookie: {
|
|
191
|
+
name: '__session',
|
|
192
|
+
secrets: [process.env.SESSION_SECRET!],
|
|
193
|
+
sameSite: 'lax',
|
|
194
|
+
path: '/',
|
|
195
|
+
httpOnly: true,
|
|
196
|
+
secure: process.env.NODE_ENV === 'production',
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
export async function requireAuth(request: Request) {
|
|
201
|
+
const session = await sessionStorage.getSession(request.headers.get('Cookie'));
|
|
202
|
+
const userId = session.get('userId');
|
|
203
|
+
|
|
204
|
+
if (!userId) {
|
|
205
|
+
throw redirect('/login');
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return userId;
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Adding New Resource
|
|
213
|
+
|
|
214
|
+
1. Create model (`models/{resource}.server.ts`)
|
|
215
|
+
2. Create routes:
|
|
216
|
+
- `_app.{resources}.tsx` - List page
|
|
217
|
+
- `_app.{resources}.new.tsx` - Create page
|
|
218
|
+
- `_app.{resources}.$id.tsx` - Detail/Edit page
|
|
219
|
+
3. Add Prisma model to `schema.prisma`
|
|
220
|
+
4. Run `pnpm db:push`
|
|
221
|
+
|
|
222
|
+
## API Routes
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
// routes/api.users.ts
|
|
226
|
+
import { json, type ActionFunctionArgs, type LoaderFunctionArgs } from '@remix-run/node';
|
|
227
|
+
|
|
228
|
+
export async function loader({ request }: LoaderFunctionArgs) {
|
|
229
|
+
const users = await getUsers();
|
|
230
|
+
return json(users);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export async function action({ request }: ActionFunctionArgs) {
|
|
234
|
+
const method = request.method;
|
|
235
|
+
|
|
236
|
+
if (method === 'POST') {
|
|
237
|
+
const data = await request.json();
|
|
238
|
+
const user = await createUser(data);
|
|
239
|
+
return json(user, { status: 201 });
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return json({ error: 'Method not allowed' }, { status: 405 });
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Configuration
|
|
247
|
+
|
|
248
|
+
### Environment Variables (.env)
|
|
249
|
+
```
|
|
250
|
+
DATABASE_URL="postgresql://user:password@localhost:5432/db"
|
|
251
|
+
SESSION_SECRET="your-secret-key"
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Prisma Schema
|
|
255
|
+
```prisma
|
|
256
|
+
// prisma/schema.prisma
|
|
257
|
+
generator client {
|
|
258
|
+
provider = "prisma-client-js"
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
datasource db {
|
|
262
|
+
provider = "postgresql"
|
|
263
|
+
url = env("DATABASE_URL")
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
model User {
|
|
267
|
+
id String @id @default(cuid())
|
|
268
|
+
email String @unique
|
|
269
|
+
name String
|
|
270
|
+
createdAt DateTime @default(now())
|
|
271
|
+
updatedAt DateTime @updatedAt
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Remix Config
|
|
276
|
+
```javascript
|
|
277
|
+
// remix.config.js
|
|
278
|
+
export default {
|
|
279
|
+
ignoredRouteFiles: ['**/.*'],
|
|
280
|
+
serverModuleFormat: 'esm',
|
|
281
|
+
tailwind: true,
|
|
282
|
+
postcss: true,
|
|
283
|
+
};
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Error Handling
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
// routes/_app.users.$id.tsx
|
|
290
|
+
export function ErrorBoundary() {
|
|
291
|
+
const error = useRouteError();
|
|
292
|
+
|
|
293
|
+
if (isRouteErrorResponse(error)) {
|
|
294
|
+
return (
|
|
295
|
+
<div>
|
|
296
|
+
<h1>{error.status} {error.statusText}</h1>
|
|
297
|
+
<p>{error.data}</p>
|
|
298
|
+
</div>
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return <div>An unexpected error occurred</div>;
|
|
303
|
+
}
|
|
304
|
+
```
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { createRequire } from 'module';
|
|
5
|
+
import { installCommand } from '../dist/commands/install.js';
|
|
6
|
+
import { uninstallCommand } from '../dist/commands/uninstall.js';
|
|
7
|
+
import { listCommand } from '../dist/commands/list.js';
|
|
8
|
+
import { postinstallCommand } from '../dist/commands/postinstall.js';
|
|
9
|
+
import { enableCommand } from '../dist/commands/enable.js';
|
|
10
|
+
import { disableCommand } from '../dist/commands/disable.js';
|
|
11
|
+
import { statusCommand } from '../dist/commands/status.js';
|
|
12
|
+
|
|
13
|
+
const require = createRequire(import.meta.url);
|
|
14
|
+
const pkg = require('../package.json');
|
|
15
|
+
|
|
16
|
+
const program = new Command();
|
|
17
|
+
|
|
18
|
+
program
|
|
19
|
+
.name('moicle')
|
|
20
|
+
.description('CLI for managing AI code editor agents, commands, and skills')
|
|
21
|
+
.version(pkg.version);
|
|
22
|
+
|
|
23
|
+
program
|
|
24
|
+
.command('install')
|
|
25
|
+
.description('Install agents, commands, and skills')
|
|
26
|
+
.option('-g, --global', 'Install globally')
|
|
27
|
+
.option('-p, --project', 'Install to current project')
|
|
28
|
+
.option('-a, --all', 'Install both globally and to project')
|
|
29
|
+
.option('-t, --target <editor>', 'Target editor (claude, cursor, windsurf, antigravity)')
|
|
30
|
+
.option('--no-symlink', 'Copy files instead of creating symlinks')
|
|
31
|
+
.action(installCommand);
|
|
32
|
+
|
|
33
|
+
program
|
|
34
|
+
.command('uninstall')
|
|
35
|
+
.description('Remove installed agents, commands, and skills')
|
|
36
|
+
.option('-g, --global', 'Uninstall from ~/.claude/')
|
|
37
|
+
.option('-p, --project', 'Uninstall from current project ./.claude/')
|
|
38
|
+
.option('-a, --all', 'Uninstall from both locations')
|
|
39
|
+
.action(uninstallCommand);
|
|
40
|
+
|
|
41
|
+
program
|
|
42
|
+
.command('list')
|
|
43
|
+
.description('List installed agents, commands, and skills')
|
|
44
|
+
.option('-g, --global', 'List global installations')
|
|
45
|
+
.option('-p, --project', 'List project installations')
|
|
46
|
+
.action(listCommand);
|
|
47
|
+
|
|
48
|
+
program
|
|
49
|
+
.command('postinstall', { hidden: true })
|
|
50
|
+
.description('Run after npm install')
|
|
51
|
+
.action(postinstallCommand);
|
|
52
|
+
|
|
53
|
+
program
|
|
54
|
+
.command('enable [item]')
|
|
55
|
+
.description('Enable agents, commands, or skills (interactive)')
|
|
56
|
+
.option('-g, --global', 'Enable in global ~/.claude/')
|
|
57
|
+
.option('-p, --project', 'Enable in current project ./.claude/')
|
|
58
|
+
.option('-a, --all', 'Enable all disabled items')
|
|
59
|
+
.action(enableCommand);
|
|
60
|
+
|
|
61
|
+
program
|
|
62
|
+
.command('disable [item]')
|
|
63
|
+
.description('Disable agents, commands, or skills (interactive)')
|
|
64
|
+
.option('-g, --global', 'Disable in global ~/.claude/')
|
|
65
|
+
.option('-p, --project', 'Disable in current project ./.claude/')
|
|
66
|
+
.option('-a, --all', 'Disable all enabled items')
|
|
67
|
+
.action(disableCommand);
|
|
68
|
+
|
|
69
|
+
program
|
|
70
|
+
.command('status')
|
|
71
|
+
.description('Show enabled/disabled status of all items')
|
|
72
|
+
.option('-g, --global', 'Show global status')
|
|
73
|
+
.option('-p, --project', 'Show project status')
|
|
74
|
+
.action(statusCommand);
|
|
75
|
+
|
|
76
|
+
program.parse();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disable.d.ts","sourceRoot":"","sources":["../../src/commands/disable.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAmC,MAAM,aAAa,CAAC;AA2HnF,eAAO,MAAM,cAAc,GACzB,UAAU,MAAM,GAAG,SAAS,EAC5B,SAAS,cAAc,KACtB,OAAO,CAAC,IAAI,CA8Fd,CAAC"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { disableItem, isDisabled } from '../utils/config.js';
|
|
6
|
+
import { getAgentsDir, getCommandsDir, getSkillsDir, listItems, } from '../utils/symlink.js';
|
|
7
|
+
const printHeader = () => {
|
|
8
|
+
console.log('');
|
|
9
|
+
console.log(chalk.cyan('════════════════════════════════════════'));
|
|
10
|
+
console.log(chalk.cyan(' MoiCle - Disable'));
|
|
11
|
+
console.log(chalk.cyan('════════════════════════════════════════'));
|
|
12
|
+
console.log('');
|
|
13
|
+
};
|
|
14
|
+
const renameToDisabled = (filePath) => {
|
|
15
|
+
if (!filePath.endsWith('.disabled')) {
|
|
16
|
+
const newPath = filePath + '.disabled';
|
|
17
|
+
try {
|
|
18
|
+
fs.renameSync(filePath, newPath);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
};
|
|
27
|
+
const disableItemByName = (type, name, scope = 'global') => {
|
|
28
|
+
let dir;
|
|
29
|
+
switch (type) {
|
|
30
|
+
case 'agents':
|
|
31
|
+
dir = getAgentsDir(scope);
|
|
32
|
+
break;
|
|
33
|
+
case 'commands':
|
|
34
|
+
dir = getCommandsDir(scope);
|
|
35
|
+
break;
|
|
36
|
+
case 'skills':
|
|
37
|
+
dir = getSkillsDir(scope);
|
|
38
|
+
break;
|
|
39
|
+
default:
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
const cleanName = name.replace('@', '').replace('.md', '').replace('.disabled', '');
|
|
43
|
+
const enabledPath = path.join(dir, `${cleanName}.md`);
|
|
44
|
+
const skillPath = path.join(dir, cleanName);
|
|
45
|
+
if (fs.existsSync(enabledPath)) {
|
|
46
|
+
renameToDisabled(enabledPath);
|
|
47
|
+
}
|
|
48
|
+
else if (fs.existsSync(skillPath) && fs.statSync(skillPath).isDirectory()) {
|
|
49
|
+
try {
|
|
50
|
+
fs.renameSync(skillPath, skillPath + '.disabled');
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// ignore
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
disableItem(type, cleanName);
|
|
57
|
+
return true;
|
|
58
|
+
};
|
|
59
|
+
const getEnabledItemsByType = (type, scope) => {
|
|
60
|
+
const items = [];
|
|
61
|
+
let dir;
|
|
62
|
+
let prefix = '';
|
|
63
|
+
switch (type) {
|
|
64
|
+
case 'agents':
|
|
65
|
+
dir = getAgentsDir(scope);
|
|
66
|
+
prefix = '@';
|
|
67
|
+
break;
|
|
68
|
+
case 'commands':
|
|
69
|
+
dir = getCommandsDir(scope);
|
|
70
|
+
prefix = '/';
|
|
71
|
+
break;
|
|
72
|
+
case 'skills':
|
|
73
|
+
dir = getSkillsDir(scope);
|
|
74
|
+
break;
|
|
75
|
+
default:
|
|
76
|
+
return items;
|
|
77
|
+
}
|
|
78
|
+
const files = listItems(dir);
|
|
79
|
+
for (const file of files) {
|
|
80
|
+
if (!file.name.endsWith('.disabled')) {
|
|
81
|
+
const cleanName = file.name.replace('.md', '');
|
|
82
|
+
if (!isDisabled(type, cleanName)) {
|
|
83
|
+
items.push({
|
|
84
|
+
type,
|
|
85
|
+
name: cleanName,
|
|
86
|
+
display: `${prefix}${cleanName}`,
|
|
87
|
+
disabled: false,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return items;
|
|
93
|
+
};
|
|
94
|
+
const getAllEnabledItems = (scope) => {
|
|
95
|
+
const itemsByType = new Map();
|
|
96
|
+
itemsByType.set('agents', getEnabledItemsByType('agents', scope));
|
|
97
|
+
if (scope === 'global') {
|
|
98
|
+
itemsByType.set('commands', getEnabledItemsByType('commands', scope));
|
|
99
|
+
}
|
|
100
|
+
itemsByType.set('skills', getEnabledItemsByType('skills', scope));
|
|
101
|
+
return itemsByType;
|
|
102
|
+
};
|
|
103
|
+
const formatTypeLabel = (type) => {
|
|
104
|
+
return type.charAt(0).toUpperCase() + type.slice(1);
|
|
105
|
+
};
|
|
106
|
+
export const disableCommand = async (itemName, options) => {
|
|
107
|
+
printHeader();
|
|
108
|
+
const scope = options.project ? 'project' : 'global';
|
|
109
|
+
if (options.all) {
|
|
110
|
+
const itemsByType = getAllEnabledItems(scope);
|
|
111
|
+
let totalDisabled = 0;
|
|
112
|
+
for (const [type, items] of itemsByType) {
|
|
113
|
+
for (const item of items) {
|
|
114
|
+
disableItemByName(type, item.name, scope);
|
|
115
|
+
console.log(chalk.red(` ✗ Disabled ${item.display}`));
|
|
116
|
+
totalDisabled++;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (totalDisabled === 0) {
|
|
120
|
+
console.log(chalk.yellow(' No enabled items found.'));
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
console.log('');
|
|
124
|
+
console.log(chalk.yellow(`✓ Disabled ${totalDisabled} items`));
|
|
125
|
+
}
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (itemName) {
|
|
129
|
+
const cleanName = itemName.replace('@', '').replace('/', '');
|
|
130
|
+
let type = 'agents';
|
|
131
|
+
if (itemName.startsWith('/')) {
|
|
132
|
+
type = 'commands';
|
|
133
|
+
}
|
|
134
|
+
else if (!itemName.startsWith('@')) {
|
|
135
|
+
const skillsDir = getSkillsDir(scope);
|
|
136
|
+
if (fs.existsSync(path.join(skillsDir, cleanName))) {
|
|
137
|
+
type = 'skills';
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
disableItemByName(type, cleanName, scope);
|
|
141
|
+
console.log(chalk.yellow(` ✗ Disabled ${itemName}`));
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const itemsByType = getAllEnabledItems(scope);
|
|
145
|
+
const allItems = [];
|
|
146
|
+
for (const items of itemsByType.values()) {
|
|
147
|
+
allItems.push(...items);
|
|
148
|
+
}
|
|
149
|
+
if (allItems.length === 0) {
|
|
150
|
+
console.log(chalk.yellow(' No enabled items to disable.'));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const choices = [];
|
|
154
|
+
for (const [type, items] of itemsByType) {
|
|
155
|
+
if (items.length > 0) {
|
|
156
|
+
choices.push(new inquirer.Separator(chalk.yellow(`── ${formatTypeLabel(type)} ──`)));
|
|
157
|
+
for (const item of items) {
|
|
158
|
+
choices.push({
|
|
159
|
+
name: ` ${item.display}`,
|
|
160
|
+
value: item,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
console.log(chalk.gray(' Use SPACE to select, ENTER to confirm'));
|
|
166
|
+
console.log('');
|
|
167
|
+
const { selected } = await inquirer.prompt([
|
|
168
|
+
{
|
|
169
|
+
type: 'checkbox',
|
|
170
|
+
name: 'selected',
|
|
171
|
+
message: 'Select items to disable:',
|
|
172
|
+
choices,
|
|
173
|
+
pageSize: 20,
|
|
174
|
+
},
|
|
175
|
+
]);
|
|
176
|
+
if (selected.length === 0) {
|
|
177
|
+
console.log(chalk.yellow(' No items selected.'));
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
console.log('');
|
|
181
|
+
for (const item of selected) {
|
|
182
|
+
disableItemByName(item.type, item.name, scope);
|
|
183
|
+
console.log(chalk.red(` ✗ Disabled ${item.display}`));
|
|
184
|
+
}
|
|
185
|
+
console.log('');
|
|
186
|
+
console.log(chalk.yellow(`✓ Disabled ${selected.length} items`));
|
|
187
|
+
};
|
|
188
|
+
//# sourceMappingURL=disable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disable.js","sourceRoot":"","sources":["../../src/commands/disable.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enable.d.ts","sourceRoot":"","sources":["../../src/commands/enable.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAmC,MAAM,aAAa,CAAC;AA8HnF,eAAO,MAAM,aAAa,GACxB,UAAU,MAAM,GAAG,SAAS,EAC5B,SAAS,cAAc,KACtB,OAAO,CAAC,IAAI,CAiGd,CAAC"}
|