Unix touch with JavaScript templates. Creates files with context-aware boilerplate instead of empty content.
- Generates content based on file extension, name, and project context
- JavaScript templates (ES2023) with file system access
- Per-project or global template customization
- Built-in templates for common file types
- Fast, lightweight Go binary
go install github.com/donatj/ttouch/cmd/ttouch@latestCreate a shell script:
ttouch script.shGenerates:
#!/bin/sh
set -e
Create a Go file (detects package from existing files):
ttouch helper.goResult with existing package myapp:
package myappCreate executable:
ttouch -e deploy.shttouch [flags] <file>...
Flags:
-f- Overwrite if file exists-e- Make executable
Examples:
# Create new file
ttouch README.md
# Create multiple files
ttouch script.sh helper.go utils.js
# Create executable
ttouch -e deploy.py
# Overwrite existing file
ttouch -f existing-script.shUses modernc.org/quickjs JavaScript runtime (ES2023).
Templates live in .ttouch directories. Search starts in current directory and walks up to root (like .git).
Naming:
{ext}.js- Matches extension (e.g.,py.jsfor*.py){filename}.js- Matches filename (e.g.,readme.md.jsforREADME.md)
Filename matches take precedence over extension matches.
Search order:
.ttouch/{filename}.jsin current directory.ttouch/{filename}.jsin parent directories.ttouch/{ext}.jsin current directory.ttouch/{ext}.jsin parent directories- Built-in templates
Minimal template:
"#!/bin/sh\n";With IIFE:
(function () {
return "#!/bin/sh\n";
})();Arrow function:
(() => {
return "#!/usr/bin/env python3\n\ndef main():\n pass\n";
})();Template value is the last expression in the file.
Templates access file information via VM:
{
"Filename": "script.sh", // Relative path
"AbsFilename": "/home/user/...", // Absolute path
"Flags": { // CLI flags
"Executable": false,
"Overwrite": true,
"Files": ["script.sh"]
}
}Example:
(() => {
if (VM.Flags.Executable) {
return "#!/usr/bin/env python3\n\n# Executable script\n";
}
return "# Python module\n";
})();Read file contents.
const content = ReadFile("package.json");
const pkg = JSON.parse(content);Match files by pattern.
const goFiles = Glob("*.go");Find file in current or parent directories.
const configs = ScanUp("package.json");Split path into [directory, filename].
const [dir, file] = SplitPath(VM.AbsFilename);Debug output.
Log("Creating file:", VM.Filename);- dot.js - Dotfiles
- go.js - Go files with package detection
- md.js - Markdown with directory heading
- php.js - PHP with PSR-4 namespaces
- sh.js - Shell scripts
Create .ttouch/py.js:
(() => {
let content = "#!/usr/bin/env python3\n";
content += '"""Module docstring."""\n\n';
if (VM.Filename.includes("test_")) {
content += "import unittest\n\n";
content += "class TestCase(unittest.TestCase):\n";
content += " def test_example(self):\n";
content += " pass\n\n";
content += 'if __name__ == "__main__":\n';
content += " unittest.main()\n";
} else {
content += "def main():\n";
content += " pass\n\n";
content += 'if __name__ == "__main__":\n';
content += " main()\n";
}
return content;
})();Run ttouch test_utils.py for unittest template, ttouch utils.py for standard module.
- Scaffold files with correct headers and imports
- Maintain consistent file structure across teams
- Generate boilerplate that adapts to existing code
- Learn language file conventions
- Automate multi-file generation
- Use
Log()for debugging - Start with static templates, add logic later
- Review built-in templates for examples
- Commit
.ttouchdirectory for team sharing - Place common templates in parent directories for project-wide use