| name | freesurfer-tool |
| description | Use this skill whenever the user wants to process structural MRI data (T1w, T2w, FLAIR, etc.) with FreeSurfer, especially for cortical/subcortical segmentation, surface reconstruction, parcellation, cortical thickness, volume statistics, or full recon-all pipeline. Triggers include: 'freesurfer', 'recon-all', 'segment MRI', 'FreeSurfer processing', 'cortical segmentation', 'subcortical segmentation', 'run recon-all', 'freesurfer T1', 'process brain MRI with freesurfer', 'aseg aparc', or any request to run FreeSurfer on NIfTI MRI data for research analysis. |
| license | MIT License (NeuroClaw custom skill – freely modifiable within the project) |
| layer | base |
| skill_type | tool |
| dependencies | ["claw-shell"] |
FreeSurfer Tool
Overview
FreeSurfer is the gold-standard open-source suite for automated reconstruction of the brain’s cortical surface from structural MRI, including skull-stripping, intensity normalization, Talairach registration, cortical parcellation (Desikan-Killiany / Destrieux atlases), subcortical segmentation (aseg), surface mesh generation, cortical thickness estimation, and statistics.
This skill serves as the NeuroClaw interface-layer wrapper for FreeSurfer and strictly follows the hierarchical design:
- Check whether FreeSurfer is installed (
recon-all --version, $FREESURFER_HOME environment variable).
- If not found → immediately invoke
dependency-planner to plan and (after user confirmation) install the latest stable FreeSurfer release + license setup.
- Collect and confirm: input NIfTI file(s), subject ID, output
SUBJECTS_DIR, desired stages/flags (e.g. -all, -autorecon1..3, -T2, -FLAIR, -parallel).
- Generate a clear, numbered execution plan including exact shell commands.
- Present plan, estimated runtime, disk/RAM requirements, and risks → wait for explicit user confirmation (“YES” / “execute” / “proceed”).
- On confirmation → delegate all shell command execution to the
claw-shell skill (environment setup, recon-all invocation, logging, progress monitoring).
- Report completion status, log location, output directory, and next steps.
Key design principle (2026 update): No direct subprocess.run() calls for long-running FreeSurfer commands. All shell execution is routed through claw-shell for centralized logging, timeout handling, real-time output streaming, and interruption safety.
Research use only.
Quick Reference (Common Use Cases)
| Task | Recommended recon-all flags / approach |
|---|
| Full pipeline (most common) | -all |
| Fast subcortical + basic surfaces | -autorecon1 -autorecon2 -autorecon3 |
| Cortical surfaces & parcellation | -autorecon2 -autorecon3 (after autorecon1 completed) |
| Improve pial surface with T2 | -T2 T2w.nii.gz |
| Use FLAIR for better segmentation | -FLAIR FLAIR.nii.gz |
| Enable multi-core acceleration | -parallel -openmp 8 (or match available cores) |
| Resume interrupted run | Omit -i and -all, specify stages only |
| Generate statistics only | -stats |
Installation Check & Setup
Installation is fully delegated to dependency-planner.
When FreeSurfer is not detected:
- Call
dependency-planner with request:
"Install latest stable FreeSurfer (8.1.0 or newer) on current OS, including license.txt setup"
- After user confirms the installation plan →
dependency-planner handles download, package install, license placement
- This skill then verifies
$FREESURFER_HOME and recon-all availability
Prerequisites:
dependency-planner (mandatory for installation)
claw-shell (mandatory for command execution)
- Valid FreeSurfer academic license (free registration required)
- ≥16 GB RAM recommended (32 GB+ strongly preferred for
-all)
Agent Reference Rule
When the agent needs FreeSurfer processing implementation code, it should first consult the curated snippet in skills/freesurfer-tool/scripts/ instead of copying from the embedded wrapper below.
Reference snippet available:
scripts/freesurfer_processor.py -> recon-all pipeline orchestration: environment setup, stage selection, parallel flags, claw-shell delegation
Example:
python skills/freesurfer-tool/scripts/freesurfer_processor.py \
--input-mri sub-001_T1w.nii.gz \
--subjid sub-001 \
--subjects-dir /data/freesurfer_output \
--stages all \
--extra-flags "-T2 T2.nii.gz -parallel -openmp 12"
NeuroClaw recommended wrapper script
import argparse
import os
import sys
from pathlib import Path
from datetime import datetime
def check_freesurfer_installed():
return False, "FreeSurfer not found (simulation mode)"
def delegate_to_claw_shell(commands, purpose, log_tag):
print(f"[Delegating to claw-shell] Purpose: {purpose}")
print(f"Log tag: {log_tag}")
print("Commands to execute:")
for cmd in commands:
print(" " + cmd)
def main():
parser = argparse.ArgumentParser(description="NeuroClaw FreeSurfer Processor")
parser.add_argument("--input-mri", required=True, help="Path to T1w (or other) NIfTI file")
parser.add_argument("--subjid", required=True, help="Subject ID (e.g. sub-001)")
parser.add_argument("--subjects-dir", required=True, help="Output SUBJECTS_DIR path")
parser.add_argument("--stages", default="all", help="all / autorecon1 / autorecon2 / autorecon3 / stats / comma-separated stages")
parser.add_argument("--extra-flags", default="", help="Additional flags, e.g. '-T2 T2.nii.gz -FLAIR FLAIR.nii.gz -parallel -openmp 12'")
parser.add_argument("--plan-only", action="store_true", help="Show plan without execution")
args = parser.parse_args()
installed, version_info = check_freesurfer_installed()
if not installed:
print("FreeSurfer not detected on system.")
print("→ Invoking dependency-planner to install FreeSurfer and set up license.")
print("Please complete the dependency-planner confirmation flow first.")
sys.exit(1)
print("FreeSurfer detected:", version_info)
subjects_dir = Path(args.subjects_dir).resolve()
print(f"\nProcessing plan for subject: {args.subjid}")
print(f"Input MRI : {args.input_mri}")
print(f"Output dir : {subjects_dir}")
print(f"Stages : {args.stages}")
if args.extra_flags:
print(f"Extra flags : {args.extra_flags}")
commands = []
fs_home = "/usr/local/freesurfer"
commands.append(f"export FREESURFER_HOME={fs_home}")
commands.append(f"source $FREESURFER_HOME/SetUpFreeSurfer.sh")
recon_cmd = [
"recon-all",
"-subjid", args.subjid,
"-i", args.input_mri
]
if args.stages == "all":
recon_cmd.append("-all")
elif "," in args.stages:
for stage in args.stages.split(","):
stage = stage.strip()
if stage:
recon_cmd.append(f"-{stage}")
else:
recon_cmd.append(f"-{args.stages}")
if args.extra_flags:
recon_cmd.extend(args.extra_flags.split())
if "-parallel" not in args.extra_flags and "-openmp" not in args.extra_flags:
recon_cmd.extend(["-parallel", "-openmp", "8"])
commands.append(" ".join(recon_cmd))
log_tag = f"freesurfer_{args.subjid}_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
print("\nExecution plan (to be run via claw-shell):")
for i, cmd in enumerate(commands, 1):
print(f"Step {i}: {cmd}")
print(f"\nEstimated runtime: 4–24 hours (full -all), 1–4 hours (segmentation stages only)")
print(f"Disk usage: ~2–5 GB per subject")
print(f"Logs will be captured by claw-shell under tag: {log_tag}")
if args.plan_only:
print("\nPlan-only mode — no execution performed.")
return
confirm = input("\nExecute now? Type YES to proceed: ").strip().upper()
if confirm != "YES":
print("Aborted by user.")
return
print("\nDelegating pipeline execution to claw-shell skill...")
delegate_to_claw_shell(
commands=commands,
purpose=f"FreeSurfer processing for subject {args.subjid} ({args.stages})",
log_tag=log_tag
)
print(f"→ Execution handed over to claw-shell.")
print(f"→ Check logs using tag: {log_tag}")
print(f"→ Final outputs will be in: {subjects_dir / args.subjid}")
if __name__ == "__main__":
main()
Important Notes & Limitations
- All actual shell command execution is delegated to
claw-shell (no direct subprocess calls for recon-all).
- Full
-all pipeline is very long-running → claw-shell should support background/detached mode or long timeouts.
- Input must be NIfTI (
.nii or .nii.gz); convert DICOM first using dcm2nii skill.
- Output follows standard FreeSurfer structure:
$SUBJECTS_DIR/<subjid>.
- Windows users: strongly recommended to use WSL2 (installation handled by
dependency-planner).
- License check: skill assumes
license.txt is already in place after dependency-planner run.
When to Call This Skill
- User provides structural MRI (NIfTI) and wants automated FreeSurfer processing.
- Any mention of
recon-all, aseg, aparc, cortical thickness, surface reconstruction, or FreeSurfer statistics.
Complementary / Related Skills
dependency-planner → install FreeSurfer + license
claw-shell → safe execution of long-running shell commands
conda-env-manager → manage Python environment for post-processing FreeSurfer outputs
Reference
Official site: https://surfer.nmr.mgh.harvard.edu
Latest stable release (as of 2026): FreeSurfer 8.1.0 or newer
License registration: https://surfer.nmr.mgh.harvard.edu/registration.html
Documentation: https://surfer.nmr.mgh.harvard.edu/fswiki/FreeSurferWiki
Custom NeuroClaw skill created to integrate FreeSurfer safely into the hierarchical skill structure.
Curated reference snippet in this skill:
skills/freesurfer-tool/scripts/freesurfer_processor.py
Post-Execution Verification (Harness Integration)
After FreeSurfer processing completes, this skill automatically invokes harness-core's VerificationRunner to validate output integrity:
Integrated verification checks:
from skills.harness_core import VerificationRunner, AuditLogger
verifier = VerificationRunner(task_type="freesurfer_processing")
verifier.add_check("brain_extraction",
checker=lambda: verify_brain_extraction(subjects_dir, subjid),
severity="error"
)
verifier.add_check("surface_reconstruction",
checker=lambda: verify_surface_files(subjects_dir, subjid),
severity="error"
)
verifier.add_check("thickness_bounds",
checker=lambda: verify_cortical_thickness_range(subjects_dir, subjid),
severity="warning"
)
verifier.add_check("parcellation",
checker=lambda: verify_aparc_aseg(subjects_dir, subjid),
severity="error"
)
verifier.add_check("statistics",
checker=lambda: verify_stats_files(subjects_dir, subjid),
severity="warning"
)
report = verifier.run(subjects_dir)
logger = AuditLogger(log_file=f"{subjects_dir}/{subjid}/freesurfer_verification.jsonl")
logger.log_validation(
task_name="freesurfer_processing",
subject_id=subjid,
checks_passed=len([r for r in report.results if r.passed]),
total_checks=len(report.results)
)
Output: {SUBJECTS_DIR}/{subjid}/freesurfer_verification.jsonl (structured audit log with JSONL format)
Created At: 2026-03-19 20:00 HKT
Last Updated At: 2026-04-05 02:03 HKT
Author: chengwang96