A powerful CLI tool to qraft structured project setups from GitHub template repositories. Pull standardized project templates, documentation scaffolds, and reusable resources from GitHub repositories at any stage of development.
We often use the same files and templates for our projects. This ranges from simple markdown files, to configuration files or specifc code. Often so small that you don't want to build a generator for it. But still want to have a consistent structure and not have to copy and paste files around. Here comes qraft to the rescue. qraft is a tool to pull files and directories from repositories into your project. It's like a poor man's generator. See more later in the documentation on how to register your own repositories as template sources and how to pull files from it. Here is an example repository that contains real world templates, we use for our projects: https://github.com/dasheck0/qraft-templates.
We chose the name qraft as a purposeful twist on βcraft.β It reflects the toolβs purpose: to help developers craft structured project setups quickly and consistently using modular templates. The βqβ adds uniqueness and avoids naming collisions, while still being short, intuitive, and natural to type in a CLI context:
npx qraft n8n
npx qraft copy readme --target ./docsAlso: Have you ever tried to come up with a short, unique and fitting name for your CLI tool that isn't taken already on npm?
- π GitHub Integration - Pull templates directly from GitHub repositories
- π¦ Template Boxes - Organized collections of files with metadata
- β¨ Create & Update Workflow - Create new boxes from local directories or update existing ones
- π§ Interactive Mode - Browse and select templates with rich previews
- ποΈ Registry Support - Configure multiple template registries
- π Authentication - Support for private repositories with GitHub tokens
- πΎ Local Caching - Improved performance with intelligent caching
- π― Target Directories - Flexible file placement with overwrite protection
- π Box Discovery - List and search available templates
- π Smart Detection - Automatically detects existing boxes and switches to update workflow
- π« Gitignore Management - Automatically manage .gitignore patterns for qraft files
npm install -g qraftnpx qraft <command>Suppose you have a repository dasheck0/qraft-templates with the following structure:
dasheck0/qraft-templates/
βββ n8n/
β βββ manifest.json
β βββ package.json
β βββ .env.example
β βββ ...
βββ readme/
β βββ manifest.json
β βββ README.md
β βββ ...
βββ .tasks/
βββ manifest.json
βββ .tasks/
Each directory serves as remote box that can be copied into your current directory. Each box must contain a .qraft directory with a manifest.json file with the following structure:
{
"name": "n8n",
"description": "Standard files for n8n backend projects",
"author": "Your Name",
"version": "1.0.0",
"defaultTarget": "./n8n-setup",
"tags": ["backend", "n8n", "automation"],
"exclude": ["manifest.json"],
"postInstall": [
"Please run `npm install` after qreating."
]
}Here is an overview of the paramaters of the manifest.json file:
| Parameter | Description |
|---|---|
name |
Unique name of the box. |
description |
Human-readable description of what this box contains. Is used for info command of the cli |
author |
Author of the box. |
version |
Version of the box. |
defaultTarget |
Optional default target directory when no --target is specified. |
tags |
Optional tags for categorization. Can be searched from the cli |
exclude |
Files to exclude when copying (relative to box directory). |
postInstall |
Optional post-installation steps to show to the user. |
# Copy a template to current directory
npx qraft copy n8n
# Copy to specific directory
npx qraft copy readme --target ./docs
# Force overwrite existing files
npx qraft copy .tasks --force# Add qraft patterns to .gitignore (recommended first step)
npx qraft gitignore
# Preview what would be added
npx qraft gitignore --dry-run
# Add patterns without confirmation prompts
npx qraft gitignore --force# Create a new box from current directory
npx qraft create . my-awesome-box
# Create with specific registry
npx qraft create ./my-project my-box --registry mycompany/templates
# Non-interactive mode (uses defaults)
npx qraft create ./src/components ui-components --no-interactiveWhen you run qraft create on a directory that already contains a .qraft directory with a manifest, qraft automatically detects this and switches to update mode:
# This will detect existing .qraft directory and update the box
npx qraft create ./my-existing-box
# The CLI will show:
# π Checking for existing box...
# π¦ Existing box detected!
# π Switching to update workflow...# List all available boxes
npx qraft list
# Interactive browsing mode
npx qraft list -i# Launch interactive mode for browsing and copying
npx qraft copy n8n -iWhen you create a box using qraft create, a .qraft directory is automatically created in your local directory. This directory contains:
.qraft/
βββ manifest.json # Box metadata and configuration
βββ metadata.json # Registry and sync information
Contains the box definition and metadata:
{
"name": "my-awesome-box",
"version": "1.0.0",
"description": "My awesome project template",
"author": "Your Name",
"defaultTarget": "./my-awesome-box",
"tags": ["template", "project"],
"exclude": [".git", "node_modules", ".qraft"],
"remotePath": "templates/my-awesome-box"
}Contains registry and synchronization information:
{
"sourceRegistry": "mycompany/templates",
"lastUpdated": "2025-01-13T15:30:00Z",
"version": "1.0.0"
}This approach allows qraft to:
- Track box state - Know which boxes exist locally
- Smart updates - Detect changes and suggest version increments
- Registry sync - Maintain connection to source registry
- Conflict resolution - Handle file changes intelligently
| Command | Purpose | Key Options |
|---|---|---|
copy <box> |
Copy template boxes to your project | -t, --target, -f, --force, -i, --interactive |
create <path> [name] |
Create/update boxes from local directories | -r, --registry, --no-interactive, --remote-path |
list |
Browse available template boxes | -r, --registry, -i, --interactive, --all-registries |
info <box> |
Show detailed box information | -r, --registry |
gitignore |
Manage .gitignore patterns for qraft files | -d, --dry-run, -f, --force, -v, --verbose, --directory |
config <cmd> |
Manage configuration and registries | show, set, add-registry, remove-registry |
auth <cmd> |
Handle GitHub authentication | login, logout, status, token |
cache <cmd> |
Manage local cache | status, clear, info, list |
Quick Command Reference:
# Essential workflow
npx qraft gitignore # Set up .gitignore first
npx qraft copy template-name # Copy a template
npx qraft create . my-template # Create your own template
# Discovery and information
npx qraft list # Browse available templates
npx qraft info template-name # Get template details
# Configuration and maintenance
npx qraft config show # View current settings
npx qraft cache clear # Clear cache if neededπ‘ Tip: Start with
qraft gitignoreto set up .gitignore patterns before using other qraft commands. This prevents qraft-generated files from being committed to version control.
Create a new template box from a local directory or update an existing one.
qraft create <path> [box-name] [options]Arguments:
<path>- Local directory path to create box from[box-name]- Optional box name (defaults to directory name)
Options:
-r, --registry <registry>- Target registry for the box--no-interactive- Skip interactive prompts and use defaults--remote-path <path>- Custom remote path in registry
Behavior:
- New Box: If no
.qraftdirectory exists, creates a new box with interactive prompts - Existing Box: If
.qraftdirectory exists, automatically switches to update workflow - Update Workflow: Prompts for version increment, description updates, and handles conflicts
Examples:
# Create new box from current directory
qraft create . my-project-template
# Create from specific directory
qraft create ./src/components ui-components
# Create with custom registry and remote path
qraft create ./docs documentation --registry mycompany/templates --remote-path docs/templates
# Update existing box (when .qraft directory exists)
qraft create ./my-existing-box # Automatically detects and updatesCopy a template box to your project.
qraft copy <box> [options]Options:
-t, --target <directory>- Target directory (default: current directory)-f, --force- Force overwrite existing files-r, --registry <registry>- Use specific registry-i, --interactive- Interactive mode with prompts-n, --nosync- Skip creating .qraft directory (no sync tracking)
Examples:
qraft copy n8n
qraft copy readme --target ./documentation
qraft copy .tasks --force
qraft copy myorg/custom-template --registry mycompany/templates
qraft copy config-template --nosync # Copy without sync trackingList available template boxes.
qraft list [options]Options:
-r, --registry <registry>- List boxes from specific registry--all-registries- List boxes from all configured registries-i, --interactive- Interactive browsing mode
Examples:
qraft list
qraft list --registry mycompany/templates
qraft list --interactiveShow detailed information about a template box.
qraft info <box> [options]Options:
-r, --registry <registry>- Use specific registry
Examples:
qraft info n8n
qraft info myorg/custom-template --registry mycompany/templatesManage configuration settings.
qraft config <command> [options]Subcommands:
show- Show current configurationset <key> <value>- Set configuration valueget <key>- Get configuration valueadd-registry [name] [repository]- Add a new registryremove-registry <name>- Remove a registryreset- Reset configuration to defaults
Examples:
qraft config show
qraft config set defaultRegistry mycompany/templates
qraft config add-registry mycompany mycompany/templates
qraft config remove-registry mycompanyManage GitHub authentication.
qraft auth <command> [options]Subcommands:
login- Set up GitHub authenticationtoken- Set token for specific registrylogout- Remove authenticationstatus- Check authentication status
Examples:
qraft auth login
qraft auth token --registry mycompany ghp_xxxxxxxxxxxx
qraft auth status
qraft auth logoutManage local cache.
qraft cache <command> [options]Subcommands:
status- Show cache status and statisticsclear- Clear all cached datainfo <box>- Show cache info for specific boxlist- List all cached boxes
Examples:
qraft cache status
qraft cache clear
qraft cache info n8nManage .gitignore patterns for qraft-generated files.
qraft gitignore [options]Options:
-
-d, --dry-run- Show what would be added without making changes- Displays a complete preview of changes before execution
- Shows existing patterns that would be skipped
- Provides file content preview with proposed additions
- Safe to run multiple times without side effects
- Useful for understanding what the command will do
-
-f, --force- Skip confirmation prompts and create/modify files automatically- Bypasses all interactive confirmation prompts
- Automatically creates .gitignore file if it doesn't exist
- Automatically adds patterns to existing .gitignore file
- Ideal for automation, scripts, and CI/CD environments
- Cannot be combined with --dry-run (conflicting options)
-
-v, --verbose- Show detailed output- Displays startup information and configuration
- Shows directory analysis and validation results
- Provides pattern analysis with categorization
- Reports detailed operation progress and results
- Includes post-operation validation and file verification
-
--directory <path>- Target directory (defaults to current directory)- Specifies the directory where .gitignore should be created/modified
- Path can be absolute or relative to current working directory
- Directory must exist and be writable
- Useful for batch operations across multiple projects
- Validates directory accessibility before proceeding
Description: The gitignore command adds qraft-specific patterns to your .gitignore file to prevent qraft-generated files from being committed to version control. It includes patterns for .qraft metadata directories, configuration files, and cache files.
Examples:
# Add qraft patterns to .gitignore in current directory
qraft gitignore
# Preview what patterns would be added
qraft gitignore --dry-run
# Show detailed information during execution
qraft gitignore --verbose
# Skip confirmations and add patterns automatically
qraft gitignore --force
# Add patterns to .gitignore in specific directory
qraft gitignore --directory ./my-project
# Combine verbose and dry-run for detailed preview
qraft gitignore --dry-run --verbose
# Force operation with verbose output for automation logging
qraft gitignore --force --verboseOption Combinations:
Safe exploration:
# Best practice: Always preview first
qraft gitignore --dry-run --verbose
# Then execute if satisfied
qraft gitignoreAutomation-friendly:
# Skip all prompts with detailed logging
qraft gitignore --force --verbose
# Batch operation across multiple directories
qraft gitignore --force --directory ./project1
qraft gitignore --force --directory ./project2Development workflow:
# Check what would happen in verbose detail
qraft gitignore --dry-run --verbose --directory ./new-feature
# Apply changes with confirmation
qraft gitignore --verbose --directory ./new-featureInvalid Combinations:
--dry-run --force- Conflicting options (dry-run prevents changes, force skips confirmations)- Empty
--directory ""- Invalid directory path
What gets added: The command adds the following patterns to your .gitignore file:
.qraft/- Qraft metadata directory.qraftrc- Qraft configuration fileqraft-cache/- Local cache directory*.qraft.tmp- Temporary qraft files
Behavior:
- New .gitignore: Creates a new .gitignore file with qraft patterns
- Existing .gitignore: Adds missing qraft patterns to existing file
- Duplicate detection: Skips patterns that already exist
- Confirmation prompts: Asks before creating or modifying files (unless --force is used)
- Dry-run mode: Shows exactly what would be changed without making modifications
Exit Codes:
0- Success (patterns added or no changes needed)1- Error (invalid options, permission denied, or operation failed)
Return Behavior:
- Success with changes: Patterns were added to .gitignore file
- Success without changes: All patterns already exist in .gitignore
- Success (dry-run): Preview completed successfully
- Error: Invalid options, file permissions, or unexpected errors
Common Scenarios:
Setting up a new project:
# Initialize your project
mkdir my-new-project && cd my-new-project
git init
# Add qraft patterns to .gitignore before first commit
qraft gitignore
# Now you can safely use qraft commands
qraft copy n8n
qraft create . my-project-templateAdding to existing project:
# Navigate to existing project
cd my-existing-project
# Preview what would be added
qraft gitignore --dry-run
# Add patterns with confirmation
qraft gitignoreAutomated setup (CI/CD):
# Skip confirmations for automated environments
qraft gitignore --force
# Or combine with other commands
qraft gitignore --force && qraft copy deployment-configTeam workflow:
# Team lead sets up .gitignore
qraft gitignore --verbose
# Commit the .gitignore file
git add .gitignore
git commit -m "Add qraft patterns to .gitignore"
# Team members can now safely use qraft
qraft copy shared-configMultiple projects:
# Add to multiple project directories
for dir in project1 project2 project3; do
qraft gitignore --directory ./$dir --force
doneqraft supports multiple template registries. The default registry is dasheck0/qraft-templates.
qraft config add-registry mycompany mycompany/templatesqraft config set defaultRegistry mycompany/templatesqraft copy template-name --registry mycompany/templatesFor private repositories, you'll need to set up GitHub authentication:
# Interactive setup
qraft auth login
# Or set a token directly
qraft auth token --registry mycompany ghp_xxxxxxxxxxxxBoxes can be referenced in several ways:
boxname- Uses default registryregistry/boxname- Uses specific registryowner/repo/boxname- Full GitHub path
-
Prepare your template directory:
mkdir my-awesome-template cd my-awesome-template # Add your template files... echo "# My Awesome Template" > README.md echo "console.log('Hello World');" > index.js
-
Create the box:
qraft create . my-awesome-template --registry mycompany/templates -
Interactive prompts will guide you:
π¦ Creating Box from Local Directory π― Interactive mode enabled β¨ Box Name: my-awesome-template π Description: [Enter description] π€ Author: [Your name] π·οΈ Tags: [Enter tags separated by commas] π Remote Path: templates/my-awesome-template π Analysis complete - 2 files will be uploaded β Proceed with creation? (y/N)
-
Make changes to your template:
cd my-awesome-template echo "# Updated documentation" >> README.md echo "const version = '2.0.0';" > version.js
-
Run create command (auto-detects existing box):
qraft create . -
Update workflow automatically starts:
π Checking for existing box... π¦ Existing box detected! π Switching to update workflow... π Current: my-awesome-template v1.0.0 π Suggested: my-awesome-template v1.0.1 π Update description? (current: "My awesome template") π€ Update author? (current: "Your Name") π·οΈ Update tags? (current: template, awesome) π Changes detected: βοΈ Modified: README.md β Added: version.js β Proceed with update? (y/N)
Always set up .gitignore first:
# Start any new project with qraft gitignore
mkdir my-project && cd my-project
git init
qraft gitignore # Do this before any qraft operations
git add .gitignore && git commit -m "Initial .gitignore with qraft patterns"Integrate with project initialization:
# Complete project setup workflow
mkdir awesome-app && cd awesome-app
git init
# Set up gitignore first
qraft gitignore --force
# Copy your base template
qraft copy node-app --target .
# Create your own box for future use
qraft create . awesome-app-template --registry mycompany/templates
# Everything is properly ignored
git add . && git commit -m "Initial project setup"Team onboarding:
# New team member setup
git clone https://github.com/mycompany/awesome-app.git
cd awesome-app
# .gitignore already has qraft patterns (set up by team lead)
# Safe to use qraft commands immediately
qraft copy development-config
qraft copy testing-setup-v, --verbose- Enable verbose output- For gitignore command: Shows detailed operation progress and analysis
-r, --registry <registry>- Override default registry- Not applicable to gitignore command (operates on local files only)
--help- Show help informationqraft gitignore --helpshows gitignore-specific help
--version- Show version number
Global vs Command-Specific Options:
- Global
-v, --verboseworks with gitignore command - Gitignore-specific options (
--dry-run,--force,--directory) only work with gitignore command - Global options can be combined with command-specific options:
qraft gitignore --verbose --dry-run
QRAFT_VERBOSE- Enable verbose logging (affects gitignore command output)GITHUB_TOKEN- Default GitHub token for authenticationQRAFT_FORCE- Enable force mode for all commands (skips confirmations)QRAFT_DRY_RUN- Enable dry-run mode for all commands (preview only)
Gitignore-specific behavior:
- When
QRAFT_VERBOSE=true, gitignore command automatically uses verbose output - When
QRAFT_FORCE=true, gitignore command skips all confirmation prompts - When
QRAFT_DRY_RUN=true, gitignore command only shows previews without changes - Environment variables can be overridden by explicit command-line flags
If you encounter authentication errors:
- Check your token:
qraft auth status - Set up authentication:
qraft auth login - Verify token permissions (repo access required for private repos)
If templates seem outdated:
- Clear cache:
qraft cache clear - Check cache status:
qraft cache status
If you can't connect to GitHub:
- Check internet connection
- Verify GitHub API access
- Check if behind corporate firewall
If you see this error when updating a box:
- Check that
.qraft/manifest.jsonexists and is valid JSON - Ensure all required fields are present (name, version, description, author)
- Recreate the box if manifest is severely corrupted:
rm -rf .qraft && qraft create .
- Set a default registry:
qraft config set defaultRegistry owner/repo - Or specify registry explicitly:
qraft create . box-name --registry owner/repo
If qraft create doesn't detect your existing box:
- Ensure
.qraftdirectory exists in the target directory - Check that
.qraft/manifest.jsoncontains valid JSON - Verify the manifest has required fields (name, version, etc.)
If you can't create or modify .gitignore:
- Check directory permissions:
ls -la - Ensure you have write access to the target directory
- Try running with elevated permissions if necessary
- Use
--directoryoption to target a writable directory
If the command succeeds but patterns aren't in .gitignore:
- Check if patterns already exist (command skips duplicates)
- Use
--verboseflag to see detailed operation info - Use
--dry-runto preview what would be added - Verify the .gitignore file location with
--verbose
If no .gitignore file appears after running the command:
- Check if you confirmed the creation prompt (or use
--force) - Verify target directory with
--directoryoption - Check file permissions in the target directory
- Use
--verboseto see detailed execution steps
If the command doesn't complete:
- Check if there are permission prompts waiting for input
- Use
--forceto skip interactive prompts - Verify directory accessibility and permissions
- Check for filesystem issues or disk space
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- π Documentation
- π Issue Tracker
- π¬ Discussions
