Writing Scripts
Best practices for writing automation scripts in Python and Bash. Use when writing automation scripts, choosing between languages, debugging subprocess errors, or implementing error handling patterns. Load language-specific references as needed.
What this skill does
# Writing Scripts
Best practices for Python and Bash automation scripts with language-specific references for deep-dive topics.
## When to Use This Skill
Use this skill when:
- Writing new automation scripts (Python or Bash)
- Debugging subprocess errors and shell parsing issues
- Implementing error handling and validation patterns
- Choosing between Python and Bash for a task
- Setting up script templates with proper structure
## Quick Decision: Python vs Bash
### Use Bash For
- **Simple CLI orchestration** (< 100 lines)
- Piping commands: `grep pattern file | sort | uniq`
- System administration tasks
- Quick file operations
- **Performance-critical shell operations** (3-5x faster than Python)
### Use Python For
- **Complex logic** (> 100 lines)
- Data processing and transformation
- Cross-platform compatibility
- API calls and HTTP requests
- Testing and debugging requirements
### Decision Matrix
| Task | Bash | Python |
|------|------|--------|
| Chain CLI tools | ✅ | ❌ |
| < 100 lines | ✅ | 🟡 |
| Data manipulation | ❌ | ✅ |
| Cross-platform | ❌ | ✅ |
| Testing needed | ❌ | ✅ |
| Complex logic | ❌ | ✅ |
| API calls | 🟡 | ✅ |
## Core Principles
### 1. Safety First
- Always implement error handling (Python: try/except, Bash: set -Eeuo pipefail)
- Provide dry-run mode for destructive operations
- Create automatic backups before modifications
- Validate inputs and check for required commands
### 2. Self-Documenting Output
- Print clear progress messages
- Show what the script is doing at each step
- Use structured output (headers, separators)
- Write errors to stderr, not stdout
### 3. Maintainability
- Keep scripts under 500 lines (split if larger)
- Use functions for repeated logic
- Document non-obvious patterns
- Include usage examples in help text
## Language-Specific References
For detailed patterns and examples, read the appropriate reference file:
### Python Reference (`references/python.md`)
Load when working with Python scripts. Contains:
- Subprocess patterns (two-stage, avoiding shell=True)
- Debugging subprocess failures
- Error handling with try/except
- Argparse patterns for CLI arguments
- Environment variable management
- File processing patterns
- URL verification examples
- Common pitfalls and solutions
**Read this when:** Writing Python scripts, debugging subprocess issues, setting up CLI arguments
### Bash Reference (`references/bash.md`)
Load when working with Bash scripts. Contains:
- Error handling (set -Eeuo pipefail, trap)
- String escaping for LaTeX and special characters
- Variable quoting rules
- Function patterns and documentation
- Script directory detection
- Configuration file loading
- Parallel processing patterns
- Common pitfalls (unquoted variables, escape sequences)
**Read this when:** Writing Bash scripts, handling LaTeX generation, debugging string escaping issues
## Common Patterns Across Languages
### Dry-Run Mode
Provide a way to preview changes before applying:
**Python:**
```python
parser.add_argument('--force', action='store_true',
help='Apply changes (dry-run by default)')
args = parser.parse_args()
dry_run = not args.force
if dry_run:
print(f"→ Would rename {old} → {new}")
else:
print(f"✓ Renamed {old} → {new}")
apply_change()
```
**Bash:**
```bash
DRY_RUN=true
[[ "${1}" == "--force" ]] && DRY_RUN=false
if $DRY_RUN; then
echo "→ Would delete $file"
else
echo "✓ Deleted $file"
rm "$file"
fi
```
### Automatic Backups
Create timestamped backups before modifications:
**Python:**
```python
from datetime import datetime
import shutil
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
backup_path = f"{config_path}.backup.{timestamp}"
shutil.copy2(config_path, backup_path)
print(f"✓ Backup created: {backup_path}")
```
**Bash:**
```bash
backup_file="${config}.backup.$(date +%Y%m%d_%H%M%S)"
cp "$config" "$backup_file"
echo "✓ Backup created: $backup_file"
```
### Check Required Commands
**Python:**
```python
import shutil
if not shutil.which('jq'):
print("Error: jq is required but not installed", file=sys.stderr)
sys.exit(1)
```
**Bash:**
```bash
if ! command -v jq &> /dev/null; then
echo "Error: jq is required but not installed" >&2
exit 1
fi
```
## Validation Tools
### Python
```bash
python3 -m py_compile script.py # Check syntax
pylint script.py # Lint
black script.py # Format
mypy script.py # Type check
```
### Bash
```bash
bash -n script.sh # Check syntax
shellcheck script.sh # Static analysis
bash -x script.sh # Debug mode
```
## How to Use This Skill
1. **Start here** - Use the decision matrix to choose Python or Bash
2. **Read language reference** - Load `references/python.md` or `references/bash.md` for detailed patterns
3. **Apply core principles** - Implement safety, documentation, and maintainability patterns
4. **Validate** - Run syntax checkers and linters before using the script
The references contain detailed code examples, debugging workflows, and common pitfalls specific to each language. Load them as needed to avoid cluttering context when working on single-language scripts.
Related in Writing & Docs
jax-development
IncludedUse this skill when the user is writing, debugging, profiling, refactoring, reviewing, benchmarking, parallelising, exporting, or explaining JAX code, or when they mention JAX, jax.numpy, jit, grad, value_and_grad, vmap, scan, lax, random keys, pytrees, jax.Array, sharding, Mesh, PartitionSpec, NamedSharding, pmap, shard_map, Pallas, XLA, StableHLO, checkify, profiler, or the JAX repo. It helps turn NumPy or PyTorch-style code into pure functional JAX, fix tracer/control-flow/shape/PRNG bugs, remove recompiles and host-device syncs, choose transforms and sharding strategies, inspect jaxpr/lowering/IR, and benchmark compiled code correctly.
nature-article-writer
IncludedDrafts, rewrites, diagnostically critiques, and style-calibrates primary research manuscripts for Nature and Nature Portfolio journals. Use when the user wants a Nature-style title, summary paragraph or abstract, introduction, results, discussion, methods, figure legends, presubmission enquiry, cover letter, reviewer response, or when a scientific draft sounds generic, jargon-heavy, structurally weak, or AI-ish and needs precise, broad-reader-friendly prose without inventing data, analyses, or references. Best for primary research articles and letters rather than reviews or press releases unless explicitly adapting one.
deckrd
IncludedDocument-driven framework that derives requirements, specifications, implementation plans, and executable tasks from goals through structured AI dialogue. Use when user says "write requirements", "create spec", "plan implementation", "derive tasks", "structure this feature", "break down into tasks", or "document this module". Also use for reverse engineering existing code into docs (/deckrd rev). Do NOT use for direct code writing — use /deckrd-coder after tasks are generated. Do NOT use when the user only wants to run or fix existing code without planning.
clinical-decision-support
IncludedGenerate professional clinical decision support (CDS) documents for pharmaceutical and clinical research settings, including patient cohort analyses (biomarker-stratified with outcomes) and treatment recommendation reports (evidence-based guidelines with decision algorithms). Supports GRADE evidence grading, statistical analysis (hazard ratios, survival curves, waterfall plots), biomarker integration, and regulatory compliance. Outputs publication-ready LaTeX/PDF format optimized for drug development, clinical research, and evidence synthesis.
handling-sf-data
IncludedSalesforce data operations with 130-point scoring. Use this skill to create, update, delete, bulk import/export, generate test data, and clean up org records using sf CLI and anonymous Apex. TRIGGER when: user creates test data, performs bulk import/export, uses sf data CLI commands, needs data factory patterns for Apex tests, or needs to seed/clean records in a Salesforce org. DO NOT TRIGGER when: SOQL query writing only (use querying-soql), Apex test execution (use running-apex-tests), or metadata deployment (use deploying-metadata).
accelint-ac-to-playwright
IncludedConvert and validate acceptance criteria for Playwright test automation. Use when user asks to (1) review/evaluate/check if AC are ready for automation, (2) assess if AC can be converted as-is, (3) validate AC quality for Playwright, (4) turn AC into tests, (5) generate tests from acceptance criteria, (6) convert .md bullets or .feature Gherkin files to Playwright specs, (7) create test automation from requirements. Handles both bullet-style markdown and Gherkin syntax with JSON test plan generation and validation.