docs: function setupByLink() {
      console.warn("symlink doesn't resolve __dirname.");
  
      const srcTaskDir = path.join(__dirname, 'tasks');
  
      // detect target package
      const targets = [];
      const PACKAGES_DIR = path.join(__dirname, '..');
      fs.readdirSync(PACKAGES_DIR)
      .forEach((filePath) => {
          const absPath = path.join(PACKAGES_DIR, filePath);
          if (fs.statSync(absPath).isDirectory()) {
              if (/^cdp-/.test(filePath)) {
                  // check project.config.js
                  try {
                      const config = require(path.join(absPath, 'project.config'));
                      if (config.required_tasks) {
                          targets.push({
                              path: absPath,
                              required_tasks: config.required_tasks,
                              task_dir: config.dir.task,
                          });
                      }
                  } catch (error) {
                      return; // next
                  }
              }
          }
      });
  
      // link
      targets.forEach((target) => {
          const dstTaskDir = path.join(target.path, target.task_dir);
          if (!fs.existsSync(dstTaskDir)) {
              // create tasks dir
              fs.mkdirSync(dstTaskDir);
          }
  
          target.required_tasks.forEach((task) => {
              const src = path.join(srcTaskDir, task);
              const dst = path.join(dstTaskDir, task);
              if (!fs.existsSync(src)) {
                  console.error('task not found: ' + task);
                  process.exit(1);
              }
              if (fs.existsSync(dst)) {
                  fs.unlinkSync(dst);
              }
              fs.symlinkSync(src, dst, 'file');
          });
      });
  }