SkillAgentSearch skills...

Firost

> Toolbox for command-line scripts

Install / Use

/learn @pixelastic/Firost
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

> firost

Async glob, read and write files.

I was getting tired of having to write the same helpers and wrappers for reading/writing files, so I packaged the best libraries and made an API that works well with async/await.

Filesystem methods

These methods help in finding, reading, moving and writing files on disk.

absolute(filepath)

Converts any filepath to an absolute path, resolving ~/ to home.

absolute('../path/to/file/oops/../.') // /absolute/path/to/file
absolute('~/.npmrc') // /home/tim/.npmrc

copy(source, destination)

Copy file(s)

await copy('index.html', './dist/index.html');
await copy('./foo/*.html', './dist');

download(url, path)

Download a file to specific path on disk

await download('http://www.example.com/file.jpg', './example.jpg');

emptyDir(path)

Empty the content of a directory

await emptyDir('./foo/bar');

exists(path)

Check if a file/directory exists

await exists('./foo/bar/file.ext');

gitRoot()

Returns the path of the closest directory holding a .git folder.

gitRoot(); // /home/tim/projects/firost
gitRoot('~/projects/aberlaas/lib/main.js'); // /home/tim/projects/aberlaas/

glob(pattern, options = {})

Returns an array of filepaths matching the specified glob pattern.

It will return hidden files and directories by default, but you can override it by passing hiddenFiles: false or directories: false to the options argument.

const paths = await glob(['./src/**/*.css', '!./src/**/_*.css']);
const noHiddenFiles = await glob(['./lib/**/*.js'], {
  hiddenFiles: false,
});
const noDirectories = await glob(['./lib'], { directories: false });

isDirectory(path)

Checks if the given path is a directory

if (await isDirectory('./dist')) {
  console.info('Website created');
}

isFile(path)

Checks if the given path is a file

if (await isFile('./package.json')) {
  console.info('File exists');
}

mkdirp(path)

Creates a set of nested directories if they don't yet exist.

await mkdirp('./dist/css');

move(source, destination)

Move file(s)

await move('index.html', 'index.back.html');
await move('./*.html', './dist');

packageRoot()

Returns the path of the closest directory holding a package.json file.

packageRoot(); // /home/tim/projects/firost
packageRoot('~/projects/aberlaas/lib/main.js'); // /home/tim/projects/aberlaas/

read(path)

Returns the textual content of a file located at the specified filepath.

const content = await read('./src/css/style.css');

readJson(path)

Returns the content of a JSON file as a JavaScript object.

const data = await readJson('./records.json');

readJsonUrl(url)

Returns the content of a JSON URL as a JavaScript object.

const data = await readJsonUrl('http://www.example.com/data.json');

remove(target)

Remove file(s)

await remove('index.back.html');
await remove('*.back.html');

urlToFilepath(url)

Converts an URL into a filepath suitable for writing the file to disk.

const filepath = urlToFilepath(
  'http://www.example.com/path/file.html?foo=bar'
);
// http/www.example.com/path/file_foo-bar.html

// Also works with relative utls
const filepath = urlToFilepath('path/file.html?foo=bar');
// path/file_foo-bar.html

watch(pattern, callback, {watcherName})

Watch for file change, and run specified callback with path to changed files.

function doSomething(filepath, type) {
  console.info(`File ${filepath} was just ${type}`);
}
const watcher = await watch(
  './path/to/files/*.jpg',
  doSomething,
  'my-watcher'
);

// To remove the watcher:
await unwatch('my-watch');
// or await unwatch(watcher);
// To remove all watchers:
await unwatchAll();
// To force wait until all watchers are executed
await waitForWatchers();

write(content, destination)

Write content to a file on disk.

await write('This is my content', './dist/content.txt');

writeJson(data, destination)

Write data to a JSON file on disk. Keys will be ordered alphabetically, for easier diffing of the file.

const records = [
  { name: 'foo', value: 2 },
  { value: 3, name: 'bar' },
];
await writeJson(records, './records/records.json');

Shell methods

These methods help abstracting some common CLI tasks

exit

Stop the current process with specified exitCode. Similar to process.exit.

exit(1);

consoleInfo

Display an information message

consoleInfo('Info');
// • Info

consoleWarn

Display a warning message

consoleWarn('Warning');
// ⚠ Warning

consoleError

Display an error message

consoleInfo('Error');
// ✘ Error

consoleSuccess

Display an success message

consoleSuccess('Success');
// ✔ Success

prompt(question)

Interactively ask user a question

const mood = await prompt('How do you feel?');

run(command)

Run a shell command just like in the terminal, but also allows access to stdout, stderr and exit code.

Options

| name | default value | description | | -------- | ------------- | ------------------------------------------------------------------------------------------- | | shell | false | Set to true to enable shell-specific feature (like &&, >, etc) | | stdout | true | Set to false to silence stdout | | stderr | true | Set to false to silence stderr | | stdin | false | Set to true to allow user to input keyboard keys. This sets stdout and stderr to true |

const { stdout } = await run('echo foo'); // foo
const { stderr } = await run('>&2 echo bar', { shell: true }); // foo
try {
  await run('echo foo && exit 42');
} catch (err) {
  // err.code = 42
  // err.stdout = foo
}

spinner(max)

Creates a spinner with optional max number of elements.

const progress = spinner(10);

progress.tick('Doing task 1');
progress.success('All tasks done');
// or progress.failure('All tasks failed');

shell(command)

Deprecated. Use run instead, it if much more flexible

Run the given command in a shell. Returns stdout, throws with stderr and exitCode.

try {
  const result = await shell('git checkout -b master');
  console.info('Created branch master');
} catch (err) {
  console.error(err.message);
  console.error(err.code);
}

sleep(delay)

Wait for a specific number of milliseconds

await sleep(100); // Wait for 100 ms

tmpDirectory()

Returns a random temporary folder, optionally scoped.

tmpDirectory(); // /tmp/{some-random-uuid}
tmpDirectory('firost/scope/'); // /tmp/firost/scope/{some-random-uuid}

which(command)

Returns the path to an executable on the system. Returns false if none is found.

if (!(await which('convert'))) {
  console.info('You need to install ImageMagick');
}

Utils

cache

Shared singleton to used a proxy cache.

cache.write('foo', 42);
cache.read('foo'); // 42
cache.has('foo'); // true
cache.has('nope'); // false

cache.write('key', { foo: ['one', 'two'], bar: { three: 3 } });
cache.read('key.foo'); // ['one', 'two'];
cache.read('key.bar.three'); // 3

cache.clear('key.foo');
cache.has('key.foo'); // false

cache.clearAll();
cache.has('key'); // false

captureOutput

Silence all output of the specified code, and return it instead

const actual = await captureOutput(async () => {
  console.info("This will not get displayed");
  await run('echo Test');
  await run('./no-existing-script.sh');
});
// actual.stdout: ["This will not get displayed", "Test"]
// actual.stderr: ["Command does not exist"]

error

Returns an Error with both a .code and a .message

throw error('E_ERROR', 'This failed');

normalizeUrl

Normalize a URL

normalizeUrl('http://www.there.com/index.html?sort=asc&name=firost');
// http://www.there.com/?name=firost&sort=asc

pulse

Shared event emitter to listen and emit events

pulse.on('custom', data => {
  console.info(data);
});
pulse.emit('custom', 'Hello');
// Hello

firostImpot(id)

Alternative to the default dynamic import(). Pass forceReload: true as an option to force reloading the latest version on disk, bypassing the singleton cache.

const module = await firostImport('./path/to/module.js');
const updatedModule = await firostImport('./path/to/module.js', {
  forceReload: true,
});

uuid()

Returns a unique ID that could be used in URL of filepaths.

console.info(uuid());
// V1StGXR8_Z5jdHi6B-myT

Related Skills

View on GitHub
GitHub Stars9
CategoryDevelopment
Updated18d ago
Forks2

Languages

JavaScript

Security Score

85/100

Audited on Mar 13, 2026

No findings