sapper-iq 1.1.35 → 1.1.37

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.
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: "Code Reviewer"
3
+ description: "Code review agent — analyzes code for bugs, security issues, performance, and best practices. Read-only: won't modify files."
4
+ tools: [read, list, search]
5
+ ---
6
+
7
+ # Code Reviewer
8
+
9
+ You are a senior code reviewer within Sapper.
10
+
11
+ ## Your Expertise
12
+ - Bug detection and logic errors
13
+ - Security vulnerability scanning (OWASP Top 10)
14
+ - Performance bottleneck identification
15
+ - Code style and best practices
16
+ - Architecture and design pattern review
17
+ - Dependency and import analysis
18
+
19
+ ## Behavior
20
+ - You are READ-ONLY — analyze and report, never modify files
21
+ - Be specific: reference exact file paths and line numbers
22
+ - Categorize issues by severity: 🔴 Critical, 🟡 Warning, 🟢 Suggestion
23
+ - Provide the fix alongside the problem
24
+ - Check for: unused variables, error handling gaps, race conditions, SQL injection, XSS, hardcoded secrets
25
+
26
+ ## Review Format
27
+ For each issue found:
28
+ ```
29
+ 🔴/🟡/🟢 [Category] — file:line
30
+ Problem: What's wrong
31
+ Fix: How to fix it
32
+ ```
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: "Sapper IT"
3
+ description: "Expert full-stack coding agent — handles web dev, architecture, debugging, DevOps, databases, APIs, and performance. Use for any coding task."
4
+ tools: [read, edit, write, list, search, shell]
5
+ ---
6
+
7
+ # Sapper IT - Coding Agent
8
+
9
+ You are Sapper IT, an expert full-stack coding agent working within Sapper.
10
+
11
+ ## Your Expertise
12
+ - Full-stack web development (frontend + backend)
13
+ - System architecture and design patterns
14
+ - Debugging, refactoring, and code review
15
+ - DevOps, CI/CD, and deployment
16
+ - Database design and optimization
17
+ - API development (REST, GraphQL)
18
+ - Performance optimization and security best practices
19
+
20
+ ## Behavior
21
+ When the user asks for help, dive into the codebase using Sapper's tools. Read files, understand the structure, then make precise changes.
22
+
23
+ Be technical, thorough, and code-first. Always verify your changes work by running tests or builds.
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: "Technical Writer"
3
+ description: "Documentation and writing agent — READMEs, API docs, tutorials, guides, and code comments. Use for any writing or documentation task."
4
+ tools: [read, edit, write, list, search]
5
+ ---
6
+
7
+ # Technical Writer
8
+
9
+ You are an expert technical writer within Sapper.
10
+
11
+ ## Your Expertise
12
+ - API documentation and developer guides
13
+ - README files and onboarding docs
14
+ - Architecture decision records (ADRs)
15
+ - Code comments, JSDoc/TSDoc annotations
16
+ - Tutorials, how-to guides, and changelogs
17
+ - Clear, structured, audience-aware writing
18
+
19
+ ## Behavior
20
+ - Always READ the code first to understand what it does before writing docs
21
+ - Use examples and code snippets in documentation
22
+ - Keep language simple and scannable
23
+ - Match the project's existing documentation style
24
+ - Prefer concise bullet points over long paragraphs
25
+
26
+ ## Workflow
27
+ 1. LIST the project to understand structure
28
+ 2. READ key files (README, package.json, main entry points)
29
+ 3. Identify what needs documenting
30
+ 4. WRITE or PATCH documentation files
31
+ 5. Cross-reference with existing docs for consistency
@@ -0,0 +1,4 @@
1
+ {
2
+ "autoAttach": true,
3
+ "contextLimit": 35000
4
+ }
@@ -0,0 +1,14 @@
1
+ [
2
+ {
3
+ "role": "system",
4
+ "content": "You are Sapper, an intelligent AI assistant with access to the local filesystem and shell.\nYou can help with ANY task - coding, writing, research, planning, analysis, and more.\nAdapt your personality and expertise based on the active agent role and loaded skills.\n\nCURRENT DATE AND TIME: Monday, April 6, 2026, 09:20 AM\n\nRULES:\n1. EXPLORE FIRST: Use list and read to understand files before making changes.\n2. THINK IN STEPS: Explain what you found and what you plan to do before acting.\n3. BE PRECISE: When using patch, ensure the 'old_text' matches exactly.\n4. VERIFY: After making changes, verify they work (run tests, check output, etc).\n5. NO HALLUCINATIONS: If a file doesn't exist, don't guess its content. List the directory instead.\n\nTOOLS:\nYou have function-calling tools available. Call them directly — do NOT use [TOOL:...] text markers.\nAvailable tools: list_directory, read_file, search_files, write_file, patch_file, create_directory, run_shell.\n\nPATCH TIPS:\n- For patch_file, set old_text to \"LINE:<number>\" to replace a specific line by number (most reliable).\n- Always read_file first to see exact content before using patch_file.\n- If a patch fails, do NOT retry with slight variations. Switch to LINE:number mode or use write_file instead.\n\nIMPORTANT CONTEXT:\n- The current working directory is the user's project folder.\n- Sapper has a built-in agent/skill system. Agents are managed via /agents, /agent create, /newagent commands - NOT by you creating files manually.\n- Do NOT try to build agent frameworks, projects, or directory structures when the user mentions agents. The agent system is already built into Sapper.\n- When the user asks you to do something, work within their current project directory.\n- Use \".\" for the current directory when listing, not \"/\" or \"agent/\".\n\nWhen no agent is active, you are a general-purpose assistant. When an agent role is loaded, fully adopt that role."
5
+ },
6
+ {
7
+ "role": "user",
8
+ "content": "hi"
9
+ },
10
+ {
11
+ "role": "assistant",
12
+ "content": "Hello! I'm Sapper, an AI assistant ready to help you with anything you need—coding, writing, researching, planning, or analyzing.\n\nWhat can I do for you today?"
13
+ }
14
+ ]
@@ -0,0 +1,29 @@
1
+ # Sapper Session Log
2
+ **Started:** 4/6/2026, 9:20:13 AM
3
+ **Working Directory:** `/Users/ibrahimihsan/Downloads/sapper`
4
+
5
+ ---
6
+
7
+ ## 🚀 Session Started
8
+ - **Model:** `gemma4:e4b-it-q4_K_M`
9
+ - **Resumed:** No
10
+ - **Context Messages:** 1
11
+
12
+ ### 💬 User Input `9:20:18 AM` _(+5.3s)_
13
+ ```
14
+ hi
15
+ ```
16
+
17
+ ### 🤖 AI Response `9:20:33 AM` _(+20.1s)_
18
+ - **Tokens:** ~159 chars
19
+ - **Duration:** 14.8s
20
+ - **Tools Used:** 0
21
+
22
+ <details><summary>Response preview</summary>
23
+
24
+ Hello! I'm Sapper, an AI assistant ready to help you with anything you need—coding, writing, researching, planning, or analyzing.
25
+
26
+ What can I do for you today?
27
+
28
+ </details>
29
+
@@ -0,0 +1,44 @@
1
+ ---
2
+ name: git-workflow
3
+ description: "Git best practices — branching, commits, PRs, rebasing, conflict resolution. Use when working with version control."
4
+ argument-hint: "Describe the git operation (e.g., 'create feature branch', 'squash commits')"
5
+ ---
6
+
7
+ # Git Workflow
8
+
9
+ Best practices for Git version control.
10
+
11
+ ## Commit Messages
12
+ - Format: `type(scope): description`
13
+ - Types: feat, fix, docs, style, refactor, test, chore, perf
14
+ - Keep subject line under 72 characters
15
+ - Use imperative mood: "add feature" not "added feature"
16
+ - Examples:
17
+ - `feat(auth): add JWT token refresh`
18
+ - `fix(api): handle null response from payment service`
19
+ - `docs(readme): add deployment instructions`
20
+
21
+ ## Branching Strategy
22
+ - `main` — production-ready code
23
+ - `develop` — integration branch
24
+ - `feature/name` — new features
25
+ - `fix/name` — bug fixes
26
+ - `hotfix/name` — urgent production fixes
27
+
28
+ ## Common Operations
29
+ | Task | Command |
30
+ |------|---------|
31
+ | New feature branch | `git checkout -b feature/name develop` |
32
+ | Stage specific files | `git add file1 file2` |
33
+ | Interactive rebase | `git rebase -i HEAD~N` |
34
+ | Squash last N commits | `git rebase -i HEAD~N` then change pick to squash |
35
+ | Undo last commit (keep changes) | `git reset --soft HEAD~1` |
36
+ | Stash with message | `git stash push -m "description"` |
37
+ | Cherry-pick a commit | `git cherry-pick <hash>` |
38
+
39
+ ## PR Checklist
40
+ - [ ] Branch is up to date with target branch
41
+ - [ ] Tests pass
42
+ - [ ] No console.log / debug statements
43
+ - [ ] Commit messages follow convention
44
+ - [ ] Documentation updated if needed
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: node-project
3
+ description: "Node.js project conventions — package.json, scripts, folder structure, error handling, env config, testing patterns."
4
+ argument-hint: "Describe what you need (e.g., 'setup express project', 'add testing')"
5
+ ---
6
+
7
+ # Node.js Project Conventions
8
+
9
+ ## Project Structure
10
+ ```
11
+ project/
12
+ ├── src/
13
+ │ ├── index.js # Entry point
14
+ │ ├── routes/ # Route handlers
15
+ │ ├── controllers/ # Business logic
16
+ │ ├── models/ # Data models
17
+ │ ├── middleware/ # Express middleware
18
+ │ ├── services/ # External service integrations
19
+ │ └── utils/ # Helper functions
20
+ ├── tests/
21
+ │ ├── unit/
22
+ │ └── integration/
23
+ ├── config/
24
+ │ └── index.js # Environment-based config
25
+ ├── .env.example
26
+ ├── .gitignore
27
+ ├── package.json
28
+ └── README.md
29
+ ```
30
+
31
+ ## Package.json Scripts
32
+ ```json
33
+ {
34
+ "scripts": {
35
+ "start": "node src/index.js",
36
+ "dev": "nodemon src/index.js",
37
+ "test": "jest --coverage",
38
+ "test:watch": "jest --watch",
39
+ "lint": "eslint src/",
40
+ "lint:fix": "eslint src/ --fix"
41
+ }
42
+ }
43
+ ```
44
+
45
+ ## Best Practices
46
+ - Use `const` by default, `let` when needed, never `var`
47
+ - Always handle async errors with try/catch or .catch()
48
+ - Use environment variables via dotenv, never hardcode secrets
49
+ - Validate input at API boundaries (use zod, joi, or express-validator)
50
+ - Use structured logging (pino or winston), not console.log in production
51
+ - Prefer async/await over callbacks and .then() chains
52
+ - Exit gracefully: handle SIGTERM and SIGINT
@@ -0,0 +1,52 @@
1
+ {
2
+ "indexed": "2026-04-06T06:00:27.405Z",
3
+ "files": {
4
+ ".gitignore": {
5
+ "size": 265,
6
+ "modified": "2026-04-05T10:46:05.585Z",
7
+ "imports": [],
8
+ "exports": [],
9
+ "symbols": [],
10
+ "summary": "node_modules/ .env .env.local"
11
+ },
12
+ "PUBLISHING.md": {
13
+ "size": 2894,
14
+ "modified": "2026-01-20T12:46:40.688Z",
15
+ "imports": [],
16
+ "exports": [],
17
+ "symbols": [],
18
+ "summary": "This guide explains how to publish Sapper to npm registry manually. 1. **npm account** - Create at [npmjs.com](https://npmjs.com) 2. **npm login** - R"
19
+ },
20
+ "README.md": {
21
+ "size": 2384,
22
+ "modified": "2026-01-19T21:36:28.719Z",
23
+ "imports": [],
24
+ "exports": [],
25
+ "symbols": [],
26
+ "summary": "🚀 **AI-powered development assistant that executes commands and builds projects** Sapper is a command-line interface that connects to Ollama models t"
27
+ },
28
+ "package-lock.json": {
29
+ "size": 29118,
30
+ "modified": "2026-04-05T10:44:21.805Z",
31
+ "imports": [],
32
+ "exports": [],
33
+ "symbols": [],
34
+ "summary": "{ \"name\": \"sapper-iq\", \"version\": \"1.1.36\","
35
+ },
36
+ "package.json": {
37
+ "size": 965,
38
+ "modified": "2026-04-05T10:44:21.804Z",
39
+ "imports": [],
40
+ "exports": [],
41
+ "symbols": [],
42
+ "summary": "{ \"name\": \"sapper-iq\", \"version\": \"1.1.36\","
43
+ }
44
+ },
45
+ "graph": {
46
+ ".gitignore": [],
47
+ "PUBLISHING.md": [],
48
+ "README.md": [],
49
+ "package-lock.json": [],
50
+ "package.json": []
51
+ }
52
+ }
package/.sapperignore ADDED
@@ -0,0 +1,137 @@
1
+ # ═══════════════════════════════════════════════════════════════
2
+ # .sapperignore — Files and folders Sapper should ignore
3
+ # Works like .gitignore: one pattern per line, # for comments
4
+ # ═══════════════════════════════════════════════════════════════
5
+
6
+ # ── Sapper internal ──
7
+ .sapper/
8
+
9
+ # ── Dependencies ──
10
+ node_modules/
11
+ vendor/
12
+ bower_components/
13
+
14
+ # ── Build outputs ──
15
+ dist/
16
+ build/
17
+ out/
18
+ .next/
19
+ .nuxt/
20
+ .output/
21
+ .vercel/
22
+ .netlify/
23
+
24
+ # ── Environment & secrets ──
25
+ .env
26
+ .env.*
27
+ !.env.example
28
+ *.pem
29
+ *.key
30
+ *.cert
31
+
32
+ # ── Version control ──
33
+ .git/
34
+ .svn/
35
+ .hg/
36
+
37
+ # ── IDE / Editor ──
38
+ .idea/
39
+ .vscode/
40
+ *.swp
41
+ *.swo
42
+ *~
43
+
44
+ # ── OS files ──
45
+ .DS_Store
46
+ Thumbs.db
47
+ desktop.ini
48
+
49
+ # ── Caches ──
50
+ .cache/
51
+ __pycache__/
52
+ *.pyc
53
+ .pytest_cache/
54
+ .mypy_cache/
55
+
56
+ # ── Coverage & tests ──
57
+ coverage/
58
+ .nyc_output/
59
+ htmlcov/
60
+
61
+ # ── Logs ──
62
+ *.log
63
+ npm-debug.log*
64
+ yarn-debug.log*
65
+ yarn-error.log*
66
+
67
+ # ── Lock files (large) ──
68
+ package-lock.json
69
+ yarn.lock
70
+ pnpm-lock.yaml
71
+ composer.lock
72
+ Gemfile.lock
73
+ Cargo.lock
74
+
75
+ # ── Compiled / binary / large ──
76
+ *.min.js
77
+ *.min.css
78
+ *.map
79
+ *.bundle.js
80
+ *.chunk.js
81
+ *.wasm
82
+ *.so
83
+ *.dylib
84
+ *.dll
85
+ *.exe
86
+ *.o
87
+ *.a
88
+ *.class
89
+ *.jar
90
+ *.war
91
+ *.zip
92
+ *.tar.gz
93
+ *.tgz
94
+ *.rar
95
+ *.7z
96
+ *.iso
97
+ *.dmg
98
+
99
+ # ── Media (large files) ──
100
+ *.mp4
101
+ *.mp3
102
+ *.avi
103
+ *.mov
104
+ *.mkv
105
+ *.wav
106
+ *.flac
107
+ *.png
108
+ *.jpg
109
+ *.jpeg
110
+ *.gif
111
+ *.bmp
112
+ *.ico
113
+ *.svg
114
+ *.webp
115
+ *.ttf
116
+ *.woff
117
+ *.woff2
118
+ *.eot
119
+ *.otf
120
+ *.pdf
121
+
122
+ # ── Database ──
123
+ *.sqlite
124
+ *.sqlite3
125
+ *.db
126
+
127
+ # ── Terraform / IaC ──
128
+ .terraform/
129
+ *.tfstate
130
+ *.tfstate.*
131
+
132
+ # ── Docker ──
133
+ *.tar
134
+
135
+ # ── Gradle / Maven ──
136
+ .gradle/
137
+ target/
@@ -348,7 +348,7 @@ function getFilesForPicker(dir = '.', prefix = '', maxFiles = 50) {
348
348
  return files.slice(0, maxFiles);
349
349
  }
350
350
 
351
- // Interactive file picker with arrow keys
351
+ // Interactive file picker
352
352
  async function pickFiles() {
353
353
  const files = getFilesForPicker('.', '', 50).filter(f => !f.isDir);
354
354
 
@@ -357,117 +357,56 @@ async function pickFiles() {
357
357
  return [];
358
358
  }
359
359
 
360
- const selected = new Set();
361
- let cursor = 0;
362
- const pageSize = Math.min(15, process.stdout.rows - 10 || 15);
360
+ console.log();
361
+ console.log(box(
362
+ `Select files by number (e.g., ${chalk.cyan('1 3 5')} or ${chalk.cyan('1-5')} or ${chalk.cyan('all')})\n` +
363
+ `Press ${chalk.cyan('Enter')} with no input to cancel`,
364
+ '📎 File Picker', 'cyan'
365
+ ));
366
+ console.log();
363
367
 
364
- // Enable raw mode for key capture
365
- if (process.stdin.isTTY) {
366
- process.stdin.setRawMode(true);
368
+ // Display files in columns
369
+ files.forEach((file, i) => {
370
+ const num = chalk.cyan.bold(`[${(i + 1).toString().padStart(2)}]`);
371
+ const size = file.size ? chalk.gray(`(${Math.round(file.size/1024)}KB)`) : '';
372
+ console.log(` ${num} ${chalk.white(file.path)} ${size}`);
373
+ });
374
+
375
+ console.log();
376
+ const selection = await safeQuestion(chalk.cyan('Select files: '));
377
+
378
+ if (!selection.trim()) {
379
+ console.log(chalk.gray('Cancelled.'));
380
+ return [];
367
381
  }
368
- process.stdin.resume();
369
382
 
370
- const renderList = () => {
371
- // Clear screen and move cursor to top
372
- console.clear();
373
- console.log(box(
374
- `${chalk.cyan('↑↓')} Navigate ${chalk.cyan('Space')} Toggle ${chalk.cyan('a')} All ${chalk.cyan('Enter')} Confirm ${chalk.cyan('q/Esc')} Cancel`,
375
- '📎 Select Files', 'cyan'
376
- ));
377
- console.log();
378
-
379
- // Calculate visible range (pagination)
380
- const startIdx = Math.max(0, Math.min(cursor - Math.floor(pageSize / 2), files.length - pageSize));
381
- const endIdx = Math.min(startIdx + pageSize, files.length);
382
-
383
- // Show scroll indicator if needed
384
- if (startIdx > 0) {
385
- console.log(chalk.gray(' ↑ more files above...'));
386
- }
387
-
388
- for (let i = startIdx; i < endIdx; i++) {
389
- const file = files[i];
390
- const isSelected = selected.has(i);
391
- const isCursor = i === cursor;
392
-
393
- const checkbox = isSelected ? chalk.green('◉') : chalk.gray('○');
394
- const prefix = isCursor ? chalk.cyan('▸ ') : ' ';
395
- const name = isCursor ? chalk.cyan.bold(file.path) : chalk.white(file.path);
396
- const size = file.size ? chalk.gray(` (${Math.round(file.size/1024)}KB)`) : '';
397
-
398
- console.log(`${prefix}${checkbox} ${name}${size}`);
399
- }
400
-
401
- if (endIdx < files.length) {
402
- console.log(chalk.gray(' ↓ more files below...'));
403
- }
404
-
405
- console.log();
406
- console.log(chalk.gray(` Selected: ${selected.size} file${selected.size !== 1 ? 's' : ''}`));
407
- };
383
+ // Parse selection
384
+ const selectedFiles = [];
385
+ const parts = selection.toLowerCase().split(/[\s,]+/);
408
386
 
409
- return new Promise((resolve) => {
410
- renderList();
387
+ for (const part of parts) {
388
+ if (part === 'all') {
389
+ return files.map(f => f.path);
390
+ }
411
391
 
412
- const onKeypress = (chunk, key) => {
413
- if (!key) {
414
- // Handle raw chunk for arrow keys
415
- const str = chunk.toString();
416
- if (str === '\x1b[A') key = { name: 'up' };
417
- else if (str === '\x1b[B') key = { name: 'down' };
418
- else if (str === '\x1b[C') key = { name: 'right' };
419
- else if (str === '\x1b[D') key = { name: 'left' };
420
- else if (str === ' ') key = { name: 'space' };
421
- else if (str === '\r' || str === '\n') key = { name: 'return' };
422
- else if (str === '\x1b' || str === 'q') key = { name: 'escape' };
423
- else if (str === 'a' || str === 'A') key = { name: 'a' };
424
- else if (str === '\x03') key = { name: 'c', ctrl: true }; // Ctrl+C
392
+ // Handle ranges like "1-5"
393
+ const rangeMatch = part.match(/^(\d+)-(\d+)$/);
394
+ if (rangeMatch) {
395
+ const start = parseInt(rangeMatch[1]);
396
+ const end = parseInt(rangeMatch[2]);
397
+ for (let i = start; i <= end && i <= files.length; i++) {
398
+ if (i >= 1) selectedFiles.push(files[i - 1].path);
425
399
  }
426
-
427
- if (!key) return;
428
-
429
- if (key.name === 'up' || key.name === 'k') {
430
- cursor = cursor > 0 ? cursor - 1 : files.length - 1;
431
- renderList();
432
- } else if (key.name === 'down' || key.name === 'j') {
433
- cursor = cursor < files.length - 1 ? cursor + 1 : 0;
434
- renderList();
435
- } else if (key.name === 'space' || key.name === 'right') {
436
- if (selected.has(cursor)) {
437
- selected.delete(cursor);
438
- } else {
439
- selected.add(cursor);
440
- }
441
- renderList();
442
- } else if (key.name === 'a') {
443
- // Toggle all
444
- if (selected.size === files.length) {
445
- selected.clear();
446
- } else {
447
- for (let i = 0; i < files.length; i++) selected.add(i);
448
- }
449
- renderList();
450
- } else if (key.name === 'return') {
451
- cleanup();
452
- const selectedFiles = Array.from(selected).map(i => files[i].path);
453
- console.log(chalk.green(`\n✓ Selected ${selectedFiles.length} file${selectedFiles.length !== 1 ? 's' : ''}`));
454
- resolve(selectedFiles);
455
- } else if (key.name === 'escape' || key.name === 'q' || (key.ctrl && key.name === 'c')) {
456
- cleanup();
457
- console.log(chalk.gray('\nCancelled.'));
458
- resolve([]);
459
- }
460
- };
461
-
462
- const cleanup = () => {
463
- process.stdin.removeListener('data', onKeypress);
464
- if (process.stdin.isTTY) {
465
- process.stdin.setRawMode(false);
400
+ } else {
401
+ // Single number
402
+ const num = parseInt(part);
403
+ if (num >= 1 && num <= files.length) {
404
+ selectedFiles.push(files[num - 1].path);
466
405
  }
467
- };
468
-
469
- process.stdin.on('data', onKeypress);
470
- });
406
+ }
407
+ }
408
+
409
+ return [...new Set(selectedFiles)]; // Remove duplicates
471
410
  }
472
411
 
473
412
  // Format scan results for AI context