@karedo-hq/agents 0.1.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 ADDED
@@ -0,0 +1,102 @@
1
+ # @karedo-hq/agents
2
+
3
+ Centralized agent skills, rules, and commands for our engineering team. Install shared configurations for AI-powered IDEs like Cursor, Claude Code, and more.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ # Using pnpm
9
+ pnpm dlx @karedo-hq/agents install --target cursor
10
+
11
+ # Or install globally
12
+ pnpm add -g @karedo-hq/agents
13
+ agents install --target cursor
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ### Install Configurations
19
+
20
+ Install agent configurations to your current project:
21
+
22
+ ```bash
23
+ agents install --target <ide>
24
+ ```
25
+
26
+ **Options:**
27
+
28
+ - `-t, --target <ide>` - Target IDE (required). Currently supported: `cursor`
29
+ - `-f, --force` - Overwrite existing files without prompting
30
+
31
+ **Examples:**
32
+
33
+ ```bash
34
+ # Install Cursor configurations
35
+ agents install --target cursor
36
+
37
+ # Force overwrite existing files
38
+ agents install --target cursor --force
39
+ ```
40
+
41
+ ## Supported Targets
42
+
43
+ | Target | Description | Output Directory |
44
+ | -------- | ---------------------------------------- | ---------------- |
45
+ | `cursor` | Cursor IDE rules and commands | `.cursor/` |
46
+
47
+ ## What Gets Installed
48
+
49
+ ### Rules
50
+
51
+ Rules provide guidelines and best practices for your codebase:
52
+
53
+ - **TypeScript** - General TypeScript coding standards
54
+ - **API (Backend)**
55
+ - Controllers, DTOs, Services
56
+ - MongoDB schemas, NestJS patterns
57
+ - Email templates, Tiptap templates
58
+ - **Web (Frontend)**
59
+ - Next.js guidelines, API layer patterns
60
+ - Page creation, table implementation
61
+ - Responsive dialog/drawer patterns
62
+
63
+ ### Commands
64
+
65
+ Commands are reusable workflows for common tasks:
66
+
67
+ - **commit** - Commit current work with conventional commits
68
+ - **create-pr** - Create a pull request with proper formatting
69
+ - **deslop** - Remove AI-generated code slop
70
+ - **release** - Automate the release process
71
+
72
+ ## Development
73
+
74
+ ```bash
75
+ # Install dependencies
76
+ pnpm install
77
+
78
+ # Build
79
+ pnpm build
80
+
81
+ # Watch mode
82
+ pnpm dev
83
+
84
+ # Type check
85
+ pnpm typecheck
86
+ ```
87
+
88
+ ## Adding New Rules or Commands
89
+
90
+ 1. Add your rule file to `rules/` (use `.mdc` extension for Cursor compatibility)
91
+ 2. Add your command file to `commands/` (use `.md` extension)
92
+ 3. Rebuild and publish
93
+
94
+ ## Adding New IDE Targets
95
+
96
+ 1. Create a new handler in `src/targets/<ide-name>.ts`
97
+ 2. Register it in `src/targets/index.ts`
98
+ 3. Implement the `install` function that maps `rules/` and `commands/` to the IDE's expected location
99
+
100
+ ## License
101
+
102
+ MIT
@@ -0,0 +1,26 @@
1
+ # Commit current work
2
+
3
+ Commit current work.
4
+
5
+ ## Important
6
+
7
+ - Prepend GIT_EDITOR=true to all git commands you run, especially the ones looking at diffs, so you can avoid getting blocked as you execute commands
8
+ - If you can't get any information from git diff, just using your working memory to determine what has changed
9
+
10
+ ## Instructions
11
+
12
+ Review each file individually to make sure they're related to the work you just did, then write a commit message following [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/):
13
+
14
+ ```
15
+ <type>[optional scope]: <description>
16
+
17
+ [optional body with 2~3 bullet points]
18
+ ```
19
+
20
+ Types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`, `ci`, `build`
21
+
22
+ ## Notes
23
+
24
+ - You should only commit work when instructed. Do not keep committing subsquent work unless explicitly told so
25
+
26
+ Optional: ask me if I would like to push the commit. (Only if I'm not on main)
@@ -0,0 +1,12 @@
1
+ # Open a PR
2
+
3
+ - Check that I'm in a branch other than `main` or `dev`. If not, bail and explain.
4
+ - Find the parent branch (the branch this one was created from) using merge-base with common branches (dev, main).
5
+ - Check the diff between my branch and the parent branch.
6
+ - If there's unstaged or staged work that hasn't been commited, commit all the relevant code first.
7
+ - Create the PR targeting the parent branch (use `gh pr create --base <parent-branch>`).
8
+ - Write up a quick PR in the following format:
9
+ - Title: Plain English, start with verb, no prefixes (e.g. "Add emails module" not "feat(emails): add emails module")
10
+ - Description: <TLDR> (no more than 2 sentences) plus <Description> (1~3 bullet points explaining what's changing)
11
+ - Always paste the link to the PR in your response so I can click it easily
12
+ - Prepend GIT_EDITOR=true to all git commands you run, so you can avoid getting blocked as you execute commands
@@ -0,0 +1,12 @@
1
+ # Remove AI code slop
2
+
3
+ Check the diff against the parent branch (use `dev` if not specified) and remove all AI generated slop introduced in this branch.
4
+
5
+ This includes:
6
+
7
+ - Extra comments that a human wouldn't add or is inconsistent with the rest of the file
8
+ - Extra defensive checks or try/catch blocks that are abnormal for that area of the codebase (especially if called by trusted / validated codepaths)
9
+ - Casts to any to get around type issues
10
+ - Any other style that is inconsistent with the file
11
+
12
+ Report at the end with only a 1-3 sentence summary of what you changed
@@ -0,0 +1,242 @@
1
+ # Release
2
+
3
+ This command automates the release process for an application in the monorepo.
4
+
5
+ ## Target Repository
6
+
7
+ **IMPORTANT**: Before starting, determine which repository to run this command on.
8
+
9
+ - If the user specified a repo (e.g., `api`, `web`), use that.
10
+ - If not specified, **ASK the user**: "Which repository should I run this release process on? (e.g., `api`, `web`)"
11
+
12
+ Do NOT proceed until you have confirmed the target `<repo>`.
13
+
14
+ Throughout this document, replace `<repo>` with the actual repository name (e.g., `api`, `web`).
15
+
16
+ ## Instructions
17
+
18
+ Follow these steps in order:
19
+
20
+ ### 0. Verify Git Branch and Pull Latest Changes
21
+
22
+ **CRITICAL**: Before starting, ensure you're on the `dev` branch with the latest changes.
23
+
24
+ Run from the `<repo>` directory:
25
+
26
+ ```bash
27
+ git checkout dev && git pull origin dev
28
+ ```
29
+
30
+ If the branch checkout or pull fails, stop and inform the user to resolve git issues manually.
31
+
32
+ ### 1. Determine Release PR Baseline and PR Set
33
+
34
+ Use **GitHub CLI (`gh`) whenever it is installed**. Fall back to GitHub MCP only if `gh` is unavailable.
35
+
36
+ ```bash
37
+ # Preferred (gh) - find the last merged release PR (base=main, head=dev)
38
+ gh pr list --state merged --base main --head dev --limit 100 --json number,title,mergedAt,url
39
+
40
+ # Preferred (gh) - list merged PRs into dev (high limit, use mergedAt)
41
+ gh pr list --state merged --base dev --limit 300 --json number,title,author,mergedAt,headRefName,url,body
42
+
43
+ # Fallback (MCP) - never sort by created_at; paginate and filter by merged_at
44
+ mcp_github_list_pull_requests({
45
+ owner: 'karedo-hq',
46
+ repo: '<repo>',
47
+ state: 'closed',
48
+ base: 'main',
49
+ head: 'dev',
50
+ per_page: 100,
51
+ page: 1,
52
+ });
53
+ ```
54
+
55
+ Fallback pagination rules (MCP):
56
+
57
+ - Always filter by `merged_at` and ignore `created_at`
58
+ - Fetch additional pages (`page: 2`, `page: 3`, ...) until you have all relevant PRs
59
+ - When listing PRs merged into `dev`, stop only after you have passed the `merged_at` threshold from the last release PR
60
+
61
+ **Critical**: Identify the last release PR as:
62
+
63
+ - `base = main`
64
+ - `head = dev`
65
+ - `state = merged`
66
+
67
+ Pick the most recent by `mergedAt` (do NOT search by title).
68
+
69
+ Build the PR set for the release using **mergedAt** only:
70
+
71
+ - Include PRs merged into `dev` **after** the last release PR's `mergedAt`
72
+ - Sort the final list by `mergedAt` ascending
73
+ - Do NOT use PR numbers or `createdAt` for ordering or filtering
74
+ - Do NOT cap results at 50; use a high limit (e.g., 300) or paginate until all relevant PRs are captured
75
+
76
+ If no PRs match, **STOP** and inform the user there is nothing to release.
77
+
78
+ For every included PR, read its **title and description thoroughly** and note the key user-facing impact; you will reuse that wording when updating the changelog.
79
+
80
+ ### 2. Update CHANGELOG.md
81
+
82
+ Add a new entry at the top of the changelog following this format:
83
+
84
+ ```markdown
85
+ ## [X.X.X] - MMM DD, YYYY.
86
+
87
+ One line summary of the release.
88
+
89
+ ### Added
90
+
91
+ - Bullet points of new features
92
+
93
+ ### Changed
94
+
95
+ - Bullet points of changes
96
+
97
+ ### Fixed
98
+
99
+ - Bullet points of bug fixes
100
+ ```
101
+
102
+ Rules:
103
+
104
+ - Keep it concise and high-level while accurately reflecting the PRs in the **exact PR list** from step 1.
105
+ - **Use PR titles and descriptions as the primary source of truth.** If a point is not obvious from the code diff, lean on the wording in the PR body.
106
+ - Make sure every PR from the list in step 1 influences the entry. If a PR does not warrant a line item, ensure its work is implicitly covered by another bullet.
107
+ - Only include important changes; combine related PRs into a single bullet when appropriate.
108
+ - Do not include PR numbers in the changelog entry.
109
+ - Follow the existing pattern in the file.
110
+
111
+ ### 3. Update package.json
112
+
113
+ Bump the version number in `<repo>/package.json`:
114
+
115
+ ```json
116
+ "version": "X.X.X"
117
+ ```
118
+
119
+ ### 4. Wait for User Confirmation
120
+
121
+ **STOP HERE AND WAIT FOR USER CONFIRMATION**
122
+
123
+ After updating CHANGELOG.md and package.json, present the changes to the user and ask:
124
+
125
+ "I've updated the following files for version X.X.X:
126
+
127
+ - CHANGELOG.md (added new entry with X changes)
128
+ - package.json (bumped version from Y.Y.Y to X.X.X)
129
+
130
+ Please review the changes. Should I proceed with committing and pushing these changes to dev?"
131
+
132
+ Do NOT proceed until the user explicitly confirms (e.g., "yes", "proceed", "looks good", etc.).
133
+
134
+ If the user requests changes, make the adjustments and ask for confirmation again.
135
+
136
+ ### 5. Commit and Push Changes to Dev
137
+
138
+ **CRITICAL STEP**: Only proceed after user confirmation. You MUST commit and push the version bump changes to dev BEFORE creating the PR and tag.
139
+
140
+ Use conventional commit format (run from the `<repo>` directory):
141
+
142
+ ```bash
143
+ git add CHANGELOG.md package.json && git commit -m "chore(version): Bump to vX.X.X" && git push origin dev
144
+ ```
145
+
146
+ Request `git_write` permissions for this step.
147
+
148
+ **Note**: If SSH authentication fails, the user will need to handle it manually. Wait for confirmation before proceeding.
149
+
150
+ ### 6. Prepare Release PR Details
151
+
152
+ Prepare the PR title and body, then present to user for confirmation:
153
+
154
+ **Title**: `Release vX.X.X` (must include the version)
155
+
156
+ **Body**: List of all included PRs (from step 1), in `mergedAt` order. Each entry must include only the PR number:
157
+
158
+ ```
159
+ - #1234
160
+ - #1235
161
+ ...
162
+ ```
163
+
164
+ **STOP AND WAIT FOR USER CONFIRMATION**
165
+
166
+ Ask the user: "Should I create the release PR with the above title and description?"
167
+
168
+ Do NOT proceed until the user explicitly confirms.
169
+
170
+ ### 7. Create Release Pull Request
171
+
172
+ Prefer GitHub CLI; only use MCP if `gh` is unavailable.
173
+
174
+ ```bash
175
+ # Preferred (gh)
176
+ gh pr create \
177
+ --title "Release vX.X.X" \
178
+ --base main \
179
+ --head dev \
180
+ --body "- #1234\n- #1235\n..."
181
+
182
+ # Fallback (MCP)
183
+ mcp_github_create_pull_request({
184
+ owner: 'karedo-hq',
185
+ repo: '<repo>',
186
+ title: 'Release vX.X.X',
187
+ head: 'dev',
188
+ base: 'main',
189
+ body: '- #1234\n- #1235\n...',
190
+ });
191
+ ```
192
+
193
+ ### 8. Create and Push Git Tag
194
+
195
+ **STOP AND WAIT FOR MERGE CONFIRMATION**
196
+
197
+ Ask the user to confirm the release PR has been merged into `main`.
198
+
199
+ **ONLY after the release PR is merged into `main`**, create and push the tag from `main` (run from the `<repo>` directory):
200
+
201
+ ```bash
202
+ git checkout main && git pull origin main
203
+ git tag vX.X.X
204
+ git push origin vX.X.X
205
+ git checkout dev
206
+ ```
207
+
208
+ Request `git_write` permissions for this step.
209
+
210
+ **Important**: The tag must point to the merged release commit on `main` (not `dev`). Always return to `dev` after tagging to continue development work.
211
+
212
+ ## Version Numbering
213
+
214
+ Follow semantic versioning:
215
+
216
+ - **Patch (X.X.1)**: Bug fixes, minor UI improvements
217
+ - **Minor (X.1.0)**: New features, significant changes
218
+ - **Major (1.0.0)**: Breaking changes, major releases
219
+
220
+ ## Common Pitfalls
221
+
222
+ 1. **Not on dev branch**: Always verify you're on `dev` branch before starting
223
+ 2. **Wrong PRs included**: Always verify PRs were merged to `dev`, not feature branches
224
+ 3. **Skipping user confirmation**: Always wait for explicit user approval before committing or creating PR
225
+ 4. **Forgot to commit**: The tag will point to the wrong commit if you don't commit first
226
+ 5. **Wrong version type**: Carefully determine if it's a patch, minor, or major version based on the changes
227
+ 6. **SSH authentication**: If git push fails with passphrase error, user needs to handle authentication
228
+ 7. **Left on main branch**: Always return to `dev` branch after tagging to continue development work
229
+
230
+ ## Example Output
231
+
232
+ At the end, provide a summary:
233
+
234
+ ```
235
+ ✅ Git Branch - Verified on dev branch with latest changes
236
+ ✅ CHANGELOG.md - Updated with vX.X.X entry (user confirmed)
237
+ ✅ package.json - Bumped version from X.X.X to X.X.X (user confirmed)
238
+ ✅ Git Commit - Committed and pushed version bump to dev
239
+ ✅ Release PR - Created #XXX from dev to main (user confirmed)
240
+ ✅ Git Tag - Created and pushed vX.X.X tag to origin
241
+ ✅ Git Branch - Returned to dev branch
242
+ ```
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/cli.js ADDED
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli.ts
4
+ import { Command } from "commander";
5
+
6
+ // src/install.ts
7
+ import chalk from "chalk";
8
+
9
+ // src/targets/cursor.ts
10
+ import path2 from "path";
11
+
12
+ // src/utils/fs.ts
13
+ import path from "path";
14
+ import { fileURLToPath } from "url";
15
+ import fs from "fs-extra";
16
+ function getPackageRoot() {
17
+ const currentFile = fileURLToPath(import.meta.url);
18
+ const currentDir = path.dirname(currentFile);
19
+ return path.resolve(currentDir, "..");
20
+ }
21
+ async function copyDirectory(source, target, force) {
22
+ let copied = 0;
23
+ let skipped = 0;
24
+ const sourceExists = await fs.pathExists(source);
25
+ if (!sourceExists) {
26
+ return { copied, skipped };
27
+ }
28
+ await fs.ensureDir(target);
29
+ const entries = await fs.readdir(source, { withFileTypes: true });
30
+ for (const entry of entries) {
31
+ const sourcePath = path.join(source, entry.name);
32
+ const targetPath = path.join(target, entry.name);
33
+ if (entry.isDirectory()) {
34
+ const result = await copyDirectory(sourcePath, targetPath, force);
35
+ copied += result.copied;
36
+ skipped += result.skipped;
37
+ } else {
38
+ const targetExists = await fs.pathExists(targetPath);
39
+ if (targetExists && !force) {
40
+ skipped++;
41
+ } else {
42
+ await fs.copy(sourcePath, targetPath);
43
+ copied++;
44
+ }
45
+ }
46
+ }
47
+ return { copied, skipped };
48
+ }
49
+
50
+ // src/targets/cursor.ts
51
+ var cursorTarget = {
52
+ id: "cursor",
53
+ name: "Cursor",
54
+ install: async (cwd, force) => {
55
+ const packageRoot = getPackageRoot();
56
+ const targetDir = path2.join(cwd, ".cursor");
57
+ const rulesSource = path2.join(packageRoot, "rules");
58
+ const rulesTarget = path2.join(targetDir, "rules");
59
+ const commandsSource = path2.join(packageRoot, "commands");
60
+ const commandsTarget = path2.join(targetDir, "commands");
61
+ const rulesResult = await copyDirectory(rulesSource, rulesTarget, force);
62
+ const commandsResult = await copyDirectory(commandsSource, commandsTarget, force);
63
+ return {
64
+ rulesCopied: rulesResult.copied,
65
+ commandsCopied: commandsResult.copied,
66
+ skipped: rulesResult.skipped + commandsResult.skipped
67
+ };
68
+ }
69
+ };
70
+
71
+ // src/targets/index.ts
72
+ var targets = {
73
+ cursor: cursorTarget
74
+ };
75
+ function getTarget(id) {
76
+ return targets[id];
77
+ }
78
+ function listTargets() {
79
+ return Object.keys(targets);
80
+ }
81
+
82
+ // src/install.ts
83
+ async function install(targetId, force) {
84
+ const target = getTarget(targetId);
85
+ if (!target) {
86
+ console.error(chalk.red(`Unknown target: ${targetId}`));
87
+ console.error(chalk.dim(`Available targets: ${listTargets().join(", ")}`));
88
+ process.exit(1);
89
+ }
90
+ console.log(chalk.blue(`Installing agent configurations for ${target.name}...`));
91
+ try {
92
+ const result = await target.install(process.cwd(), force);
93
+ console.log(chalk.green("\nInstallation complete!"));
94
+ console.log(chalk.dim(` Rules copied: ${result.rulesCopied}`));
95
+ console.log(chalk.dim(` Commands copied: ${result.commandsCopied}`));
96
+ if (result.skipped > 0) {
97
+ console.log(chalk.yellow(` Skipped (already exist): ${result.skipped}`));
98
+ }
99
+ } catch (error) {
100
+ const message = error instanceof Error ? error.message : String(error);
101
+ console.error(chalk.red(`Installation failed: ${message}`));
102
+ process.exit(1);
103
+ }
104
+ }
105
+
106
+ // src/cli.ts
107
+ var program = new Command();
108
+ program.name("agents").description("Install shared agent skills, rules, and commands for your IDE").version("0.1.0");
109
+ program.command("install").description("Install agent configurations to target IDE").requiredOption("-t, --target <ide>", "Target IDE (e.g., cursor)").option("-f, --force", "Overwrite existing files without prompting", false).action(async (options) => {
110
+ await install(options.target, options.force);
111
+ });
112
+ program.parse();
113
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/install.ts","../src/targets/cursor.ts","../src/utils/fs.ts","../src/targets/index.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { install } from \"./install.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"agents\")\n .description(\"Install shared agent skills, rules, and commands for your IDE\")\n .version(\"0.1.0\");\n\nprogram\n .command(\"install\")\n .description(\"Install agent configurations to target IDE\")\n .requiredOption(\"-t, --target <ide>\", \"Target IDE (e.g., cursor)\")\n .option(\"-f, --force\", \"Overwrite existing files without prompting\", false)\n .action(async (options: { target: string; force: boolean }) => {\n await install(options.target, options.force);\n });\n\nprogram.parse();\n","import chalk from \"chalk\";\nimport { getTarget, listTargets } from \"./targets/index.js\";\n\nexport async function install(targetId: string, force: boolean): Promise<void> {\n const target = getTarget(targetId);\n\n if (!target) {\n console.error(chalk.red(`Unknown target: ${targetId}`));\n console.error(chalk.dim(`Available targets: ${listTargets().join(\", \")}`));\n process.exit(1);\n }\n\n console.log(chalk.blue(`Installing agent configurations for ${target.name}...`));\n\n try {\n const result = await target.install(process.cwd(), force);\n\n console.log(chalk.green(\"\\nInstallation complete!\"));\n console.log(chalk.dim(` Rules copied: ${result.rulesCopied}`));\n console.log(chalk.dim(` Commands copied: ${result.commandsCopied}`));\n\n if (result.skipped > 0) {\n console.log(chalk.yellow(` Skipped (already exist): ${result.skipped}`));\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(`Installation failed: ${message}`));\n process.exit(1);\n }\n}\n","import path from \"node:path\";\nimport { copyDirectory, getPackageRoot } from \"../utils/fs.js\";\nimport type { InstallResult, Target } from \"./index.js\";\n\nexport const cursorTarget: Target = {\n id: \"cursor\",\n name: \"Cursor\",\n install: async (cwd: string, force: boolean): Promise<InstallResult> => {\n const packageRoot = getPackageRoot();\n const targetDir = path.join(cwd, \".cursor\");\n\n const rulesSource = path.join(packageRoot, \"rules\");\n const rulesTarget = path.join(targetDir, \"rules\");\n\n const commandsSource = path.join(packageRoot, \"commands\");\n const commandsTarget = path.join(targetDir, \"commands\");\n\n const rulesResult = await copyDirectory(rulesSource, rulesTarget, force);\n const commandsResult = await copyDirectory(commandsSource, commandsTarget, force);\n\n return {\n rulesCopied: rulesResult.copied,\n commandsCopied: commandsResult.copied,\n skipped: rulesResult.skipped + commandsResult.skipped,\n };\n },\n};\n","import path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport fs from \"fs-extra\";\n\ntype CopyResult = {\n copied: number;\n skipped: number;\n};\n\nexport function getPackageRoot(): string {\n const currentFile = fileURLToPath(import.meta.url);\n const currentDir = path.dirname(currentFile);\n return path.resolve(currentDir, \"..\");\n}\n\nexport async function copyDirectory(\n source: string,\n target: string,\n force: boolean\n): Promise<CopyResult> {\n let copied = 0;\n let skipped = 0;\n\n const sourceExists = await fs.pathExists(source);\n if (!sourceExists) {\n return { copied, skipped };\n }\n\n await fs.ensureDir(target);\n\n const entries = await fs.readdir(source, { withFileTypes: true });\n\n for (const entry of entries) {\n const sourcePath = path.join(source, entry.name);\n const targetPath = path.join(target, entry.name);\n\n if (entry.isDirectory()) {\n const result = await copyDirectory(sourcePath, targetPath, force);\n copied += result.copied;\n skipped += result.skipped;\n } else {\n const targetExists = await fs.pathExists(targetPath);\n\n if (targetExists && !force) {\n skipped++;\n } else {\n await fs.copy(sourcePath, targetPath);\n copied++;\n }\n }\n }\n\n return { copied, skipped };\n}\n","import { cursorTarget } from \"./cursor.js\";\n\nexport type InstallResult = {\n rulesCopied: number;\n commandsCopied: number;\n skipped: number;\n};\n\nexport type Target = {\n id: string;\n name: string;\n install: (cwd: string, force: boolean) => Promise<InstallResult>;\n};\n\nconst targets: Record<string, Target> = {\n cursor: cursorTarget,\n};\n\nexport function getTarget(id: string): Target | undefined {\n return targets[id];\n}\n\nexport function listTargets(): string[] {\n return Object.keys(targets);\n}\n"],"mappings":"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","names":["path","path"]}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@karedo-hq/agents",
3
+ "version": "0.1.0",
4
+ "description": "Centralized agent skills, rules, and commands for our engineering team",
5
+ "type": "module",
6
+ "bin": {
7
+ "agents": "./dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "rules",
12
+ "commands"
13
+ ],
14
+ "keywords": [
15
+ "ai",
16
+ "agents",
17
+ "cursor",
18
+ "ide",
19
+ "rules",
20
+ "commands",
21
+ "skills"
22
+ ],
23
+ "author": "Karedo",
24
+ "license": "MIT",
25
+ "dependencies": {
26
+ "chalk": "^5.3.0",
27
+ "commander": "^12.1.0",
28
+ "fs-extra": "^11.2.0"
29
+ },
30
+ "devDependencies": {
31
+ "@types/fs-extra": "^11.0.4",
32
+ "@types/node": "^22.10.0",
33
+ "tsup": "^8.3.5",
34
+ "typescript": "^5.7.2"
35
+ },
36
+ "engines": {
37
+ "node": ">=18"
38
+ },
39
+ "scripts": {
40
+ "build": "tsup",
41
+ "dev": "tsup --watch",
42
+ "typecheck": "tsc --noEmit"
43
+ }
44
+ }
@@ -0,0 +1,31 @@
1
+ ---
2
+ description: How to define API controllers on the backend.
3
+ alwaysApply: false
4
+ ---
5
+ # Controllers Guidelines
6
+
7
+ ## Multi-Tenant Architecture
8
+
9
+ - Use `@GetOrganizationId()` decorator to obtain organization scope.
10
+ - Pass `organizationId` to all service methods for scoped database operations.
11
+
12
+ ## Structure
13
+
14
+ - Controller Decorator: Use `@Controller('route-path')` to define base route.
15
+ - Route Handlers: Decorate methods with HTTP decorators (`@Get()`, `@Post()`, `@Patch(':id')`, `@Delete(':id')`).
16
+ - Use parameter decorators: `@Body()`, `@Param()`, `@Query()`, `@Req()`, `@UploadedFile()`.
17
+ - Set specific status codes with `@HttpCode(HttpStatus.CREATED)`.
18
+
19
+ ```typescript
20
+ @Post()
21
+ @HttpCode(HttpStatus.CREATED)
22
+ public async create(
23
+ @GetOrganizationId() organizationId: string,
24
+ @Body() createItemDto: CreateItemDto,
25
+ ) {
26
+ return this.itemsService.create(organizationId, createItemDto);
27
+ }
28
+ ```
29
+
30
+ - File Uploads: Use `@UseInterceptors(FileInterceptor('fieldName', options))` with `@UploadedFile()` decorator. Validate with `ParseFilePipe` and validators (`MaxFileSizeValidator`, `FileTypeValidator`).
31
+ - Request Object: Use `@Req()` for direct request access (e.g., `req.user` from auth guards). Type as `RequestWithUser`.
@@ -0,0 +1,38 @@
1
+ ---
2
+ description: How to define DTOs (data-transfer-objects) on the backend.
3
+ alwaysApply: false
4
+ ---
5
+ # DTOs Guidelines
6
+
7
+ ## Validation
8
+
9
+ Use `class-validator` decorators for input validation:
10
+
11
+ ```typescript
12
+ import {
13
+ IsString,
14
+ IsNotEmpty,
15
+ IsEmail,
16
+ IsOptional,
17
+ MinLength,
18
+ } from 'class-validator';
19
+
20
+ export class CreateUserDto {
21
+ @IsString()
22
+ @IsNotEmpty()
23
+ @MinLength(3)
24
+ username: string;
25
+
26
+ @IsEmail()
27
+ email: string;
28
+
29
+ @IsOptional()
30
+ @IsString()
31
+ displayName?: string;
32
+ }
33
+ ```
34
+
35
+ ## Principles
36
+
37
+ - Keep DTOs focused on data structure and validation only.
38
+ - No business logic in DTOs.