Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,28 +196,42 @@ $ aspens doc sync .
| Option | Description |
|--------|-------------|
| `--commits <n>` | Number of commits to analyze (default: 1) |
| `--refresh` | Review all skills against current codebase (no git diff needed) |
| `--install-hook` | Install git post-commit hook for auto-sync |
| `--remove-hook` | Remove the post-commit hook |
Comment thread
mvoutov marked this conversation as resolved.
| `--dry-run` | Preview without writing files |
| `--timeout <seconds>` | Claude timeout (default: 300) |
| `--model <model>` | Claude model (e.g., sonnet, opus, haiku) |
| `--verbose` | Show what Claude is reading in real time |

### `aspens doc graph [path]`

Rebuild the import graph cache. Runs automatically during `doc init` and `doc sync`, but you can trigger it manually.

```bash
aspens doc graph .
```

### `aspens add <type> [name]`

Add individual components from the bundled library.
Add individual components from the bundled library, or create custom skills.

```bash
aspens add agent all # Add all 9 AI agents
aspens add agent code-reviewer # Add a specific agent
aspens add agent --list # Browse available agents
aspens add hook skill-activation # Add auto-triggering hooks
aspens add command dev-docs # Add slash commands
aspens add skill my-convention # Scaffold a custom skill
aspens add skill release --from dev/release.md # Generate from a reference doc
aspens add skill --list # Show existing skills
```

| Option | Description |
|--------|-------------|
| `--list` | Browse available components |
| `--force` | Overwrite existing files |
| `--from <file>` | Generate a skill from a reference document (skills only) |
| `--force` | Overwrite existing skills |

Comment thread
coderabbitai[bot] marked this conversation as resolved.
### `aspens customize agents`

Expand Down
4 changes: 4 additions & 0 deletions bin/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ function showWelcome() {
${pc.yellow('--mode')} ${pc.dim('<mode>')} all, chunked, base-only ${pc.yellow('--timeout')} ${pc.dim('<s>')} Seconds per call
${pc.yellow('--strategy')} ${pc.dim('<s>')} improve, rewrite, skip ${pc.yellow('--json')} JSON output (scan)
${pc.yellow('--no-hooks')} Skip hook installation ${pc.yellow('--hooks-only')} Update hooks only
${pc.yellow('--no-graph')} Skip import graph analysis

${pc.bold('Typical Workflow')}
${pc.dim('$')} aspens scan ${pc.dim('1. See what\'s in your repo')}
Expand Down Expand Up @@ -121,6 +122,7 @@ program
.option('--json', 'Output as JSON')
.option('--domains <domains>', 'Additional domains to include (comma-separated)')
.option('--verbose', 'Show diagnostic output')
.option('--no-graph', 'Skip import graph analysis')
.action(scanCommand);

// Doc commands
Expand All @@ -143,6 +145,7 @@ doc
.option('--verbose', 'Show what Claude is reading/doing in real time')
.option('--no-hooks', 'Skip hook/rules/settings installation')
.option('--hooks-only', 'Skip skill generation, just install/update hooks')
.option('--no-graph', 'Skip import graph analysis')
.action(docInitCommand);

doc
Expand All @@ -157,6 +160,7 @@ doc
.option('--timeout <seconds>', 'Claude timeout in seconds', parseTimeout, 300)
.option('--model <model>', 'Claude model to use (e.g., sonnet, opus, haiku)')
.option('--verbose', 'Show what Claude is reading/doing in real time')
.option('--no-graph', 'Skip import graph analysis')
.action((path, options) => {
checkMissingHooks(resolve(path));
return docSyncCommand(path, options);
Expand Down
22 changes: 22 additions & 0 deletions src/commands/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,27 @@ function addResource(repoPath, resourceType, name, available) {

copyFileSync(sourceFile, targetFile);
console.log(` ${pc.green('+')} ${resourceType.targetDir}/${resource.fileName}`);

// Plan/execute agents need dev/ gitignored for plan storage
if (name === 'plan' || name === 'execute') {
ensureDevGitignore(repoPath);
}
Comment on lines +203 to +206

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Scope dev/ gitignore updates to agent installs only.

This condition currently runs for any resource named plan/execute, not just agents. That can cause unintended .gitignore edits for future command/hook templates with those names.

Proposed fix
-  if (name === 'plan' || name === 'execute') {
+  if (resourceType.targetDir === '.claude/agents' && (name === 'plan' || name === 'execute')) {
     ensureDevGitignore(repoPath);
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Plan/execute agents need dev/ gitignored for plan storage
if (name === 'plan' || name === 'execute') {
ensureDevGitignore(repoPath);
}
// Plan/execute agents need dev/ gitignored for plan storage
if (resourceType.targetDir === '.claude/agents' && (name === 'plan' || name === 'execute')) {
ensureDevGitignore(repoPath);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/add.js` around lines 203 - 206, The current check calls
ensureDevGitignore(repoPath) for any resource named 'plan' or 'execute';
restrict this so it only runs when those names are being added as part of an
agent install. Update the condition around ensureDevGitignore in
src/commands/add.js to require both (name === 'plan' || name === 'execute') AND
the installation target/type is an agent (e.g., check the variable that
indicates install kind such as resourceType / type / target / kind used in this
file), e.g. change to if ((name === 'plan' || name === 'execute') && target ===
'agent') { ensureDevGitignore(repoPath); } so .gitignore edits only occur for
agent installs; use the actual identifier present in this module for the install
target.

}

function ensureDevGitignore(repoPath) {
try {
const gitignorePath = join(repoPath, '.gitignore');
if (existsSync(gitignorePath)) {
const content = readFileSync(gitignorePath, 'utf8');
if (/^dev\/$/m.test(content)) return; // already present
writeFileSync(gitignorePath, content.trimEnd() + '\ndev/\n', 'utf8');
} else {
writeFileSync(gitignorePath, 'dev/\n', 'utf8');
}
console.log(` ${pc.green('+')} Added ${pc.cyan('dev/')} to .gitignore (used for plan storage)`);
} catch (err) {
throw new CliError(`Failed to update .gitignore: ${err.message}. Check file permissions.`);
}
}

// --- Custom skill ---
Expand Down Expand Up @@ -354,6 +375,7 @@ ${refContent}
allowedTools: ['Read', 'Glob', 'Grep'],
verbose,
model: options.model || null,
maxTokens: 8000,
onActivity: verbose ? (msg) => genSpinner.message(pc.dim(msg)) : null,
});
} catch (err) {
Expand Down
1 change: 1 addition & 0 deletions src/commands/customize.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export async function customizeCommand(what, options) {
allowedTools: READ_ONLY_TOOLS,
verbose,
model: options.model || null,
maxTokens: 8000,
onActivity: verbose ? (msg) => agentSpinner.message(pc.dim(msg)) : null,
});

Expand Down
Loading
Loading