Partoska Laboratory
$ cisiviv1.0.1

Cisivi

A small CSV query tool and C library for macOS, Linux, and Windows. Query, filter, sort, and edit CSV files from the command line, so your shell scripts handle quoted commas and line breaks without cut or awk.

CSV Query ToolC99 LibraryOpen Source (MIT)macOS · Linux · Windows
cisivi — terminal

# Install with npm (or Homebrew, Scoop, packages).

$ npm install -g @partoska/cisivi

# Read one column.

$ cisivi name crew.csv
Kirk
Spock
McCoy, Leonard
Janeway

# Count the rows that match.

$ cisivi -c -f ship=Enterprise . crew.csv
3

# Change a value in the file.

$ cisivi -w -s Admiral -f name=Kirk rank crew.csv

Why Cisivi?

Small and Dependency-Free

One C99 tool and one C99 library that need nothing but the standard C library. Builds with GCC, Clang, or MSVC and runs from a Raspberry Pi to a Windows desktop.

Query What You Need

Ask for the whole table with ., columns by name or by position with #N, rows with [ROWS], or one value with [0].name. Rows also count from the end.

Filter and Sort

Keep the rows you need with the -f parameter: = for text, < or >= for numbers, ~ to search inside. Order them with --sort, numbers by value.

Real CSV, Not Split Lines

Quoted commas, doubled quotes, and line breaks inside values stay in one field. Counts with the -c parameter and column names with the -k parameter count records, not lines.

Output for Scripts and People

Print CSV, raw values one per line, JSON with the -j parameter, or an aligned table with the -t parameter. The -0 parameter ends values with NUL for xargs -0.

Any Delimiter

Read semicolons, tabs, or any other character with the -F parameter and write another with --output-delimiter. LF or CRLF, with or without a header row.

Join Several Files

Give several files and Cisivi joins them in order, matching columns by name. A column new in a later file is added, and rows that lack it leave it empty.

Set, Add, and Delete

Set values with the -s parameter, append or insert rows with the -a parameter, and delete rows or columns with the -d parameter. Print the result, or write it back to the file with the -w parameter.

Exit Codes for Scripts

0 found, 1 not found, 2 usage or input error. Output in CSV stays valid CSV, ready for another cisivi.

Ready for AI Agents

Cisivi ships with an agent skill. Install it with one command, and AI coding agents such as Claude Code and Codex can query and edit your CSV files with exact commands.

$ npx skills add partoska/cisivi
Get the Cisivi skill

One Tool, One Library

The cisivi command is a thin layer over libcisivi. Use the command in shell scripts and pipelines, or link the library into your own C program.

Command-Line Tool

Reads files or standard input, prints exactly what a query selects, and edits values, rows, and columns. Made for shell scripts, Makefiles, and CI jobs.

$ cisivi -f ship=Voyager name crew.csv

C Library

Reads and writes CSV with optional headers and any delimiter, with no type conversion. It keeps rows and columns in file order and never prints anything: errors are stored in the document with their line number.

#include <cisivi.h>

Quick Start

Go from install to querying and changing a CSV file in five steps.

  1. Install cisivi

    Install the CLI and check the version. Prefer Homebrew, Scoop, or a native package? See the install options.

    $ npm install -g @partoska/cisivi
    $ cisivi -V
  2. Create a CSV file

    Write a small table to try the queries on. Its first row names the columns. Any existing .csv file with a header row works too.

    $ printf 'name,rank,age\nKirk,Captain,34\n"McCoy, Leonard",Doctor,52\nJaneway,Captain,41\n' > crew.csv
  3. Read a column

    Print the values of one column, then the whole table as an aligned table. The quoted comma stays in its value.

    $ cisivi name crew.csv
    $ cisivi -t . crew.csv
  4. Filter and sort

    Keep the rows where all filters hold, or sort the rows and take the first one.

    $ cisivi -f rank=Captain -f 'age>40' name crew.csv
    $ cisivi --sort-desc age '[0].name' crew.csv
  5. Change a value

    Set a value in the rows that match, write it back to the file with the -w parameter, then read it again.

    $ cisivi -w -s Admiral -f name=Kirk rank crew.csv
    $ cisivi -f name=Kirk rank crew.csv

Examples

Print the whole table, columns by name or position, rows by position, or single values. Negative positions count from the end, and [N:M] takes rows from N up to M. Add the -i parameter to ignore the case of column names.

crew.csv
id,name,rank,age,ship1,Kirk,Captain,34,Enterprise2,Spock,Commander,35,Enterprise3,"McCoy, Leonard",Doctor,52,Enterprise4,Janeway,Captain,41,Voyager
$ cisivi . crew.csv
$ cisivi name crew.csv
$ cisivi name,ship crew.csv
$ cisivi '#1' crew.csv
$ cisivi '[-1].name' crew.csv
$ cisivi '[1:3].name,ship' crew.csv
$ cat crew.csv | cisivi -i NAME

More options are in the documentation.

Install

Pick the method that fits your system. Every option installs the same cisivi tool.

$ brew install partoska/tap/cisivi

For macOS and Linux on x64 and ARM64.

Commands use the latest version, 1.0.1. See the release page for all files and SHA256 checksums.

Add the AI Agent Skill

Let AI coding agents such as Claude Code and Codex run cisivi for you. The installer adds the Cisivi skill to the skills directory of your agent. In Claude, you can also upload cisivi_1.0.1_skill.zip from the release page as a custom skill. Install cisivi itself first.

$ npx skills add partoska/cisivi

Reference

Run cisivi [OPTIONS] [QUERY] [FILE...]. It reads every FILE in order, or standard input when there is none or the file is -. The query always comes first. Run cisivi -h for the built-in help.

Queries

.
The whole table, as CSV (default).
COLUMN
The values of one column, one per line.
COLUMN,...
Several columns, as CSV.
#N
A column by position, counted from 0.
"NAME"
A quoted column name, which may contain commas or quotes. Inside quotes, \" and \\ escape.
[ROWS]
Rows by position, as CSV: [N], [-N] from the end, [N:M] from N up to M, [N:], [:M], or [*].
[ROWS].COLUMN
Rows and columns together, such as [0].name for one value.

Filter operators

=, !=
Equal or not equal, as exact text.
<, <=, >, >=
Ordered: numbers by value, other text byte by byte.
~, !~
Contains the value, or does not.

Exit status

0
Found, or the edit worked.
1
Not found: a missing column, or no row selected. The header is still printed, so the output stays valid CSV.
2
Usage or input error, including CSV syntax errors with their line on standard error.

Options

-f, --filter EXPR
Keep the rows where COLUMN OPERATOR VALUE holds. Repeat it to require all.
--sort COLUMN
Order the rows by COLUMN, numbers by value.
--sort-desc COLUMN
The same, in descending order.
-k, --keys
List the column names, one per line.
-c, --count
Print the number of rows selected.
-s, --set VALUE
Set the column of the query to the value in the selected rows, adding the column when missing.
-a, --add ROW
Append one record given as CSV text, or with [N] insert it as row N.
-d, --delete
Delete the selected rows, or the columns the query names.
-w, --write
Write the edit back to FILE instead of printing it. Needs exactly one file.
-j, --json
Print JSON: an array with an object per row.
-t, --table
Print an aligned table for reading.
-0, --null
End raw values and names with NUL instead of a newline.
-F, --delimiter C
Read fields separated by C, such as ; or tab.
--output-delimiter C
Write fields separated by C. By default, as read.
--crlf
End written rows with CRLF instead of LF.
-n, --no-header
Read the first row as data. Columns are then addressed as #N.
-i, --ignore-case
Match column names case-insensitively (ASCII).
-h, --help
Show the help.
-V, --version
Show the version.

Library

csInit, csDestroy
Create and free a document. The flag CS_FHEADER makes the first row the header, CS_FICASE matches names case-insensitively, and CS_FLF turns line breaks inside values into LF.
csLoad, csSave
Load a document from a file, or save it to a file.
csRead, csWrite
Pull or push the text through your own callbacks: standard input, a socket, or memory.
csParse
Parse CSV text from a string.
csGet, csSet
Read or replace the value of a field by row and column. With a header, row 0 holds the column names.
csRowAdd, csRowInsert
Append a row, or insert one at a position. csRowRemove and csRowRemoveMany remove rows.
csRowCount, csRowAt
Count the rows, header included, and walk them in document order.
csColumnFind, csColumnName
Find a column by name, or get the name of one. csColumnCount counts them.
csColumnAdd, csColumnInsert
Add a column filled with a value, or insert one at a position. csColumnRemove removes one.
csSetDelimiter, csSetNewline
Choose the field separator for reading and writing, and what ends written rows.
csWriteRow
Write a single record with the settings of a document, for rows produced one at a time.
csError
Get the last error with its status, line, and message.

See cisivi.h for the whole API. Include cisivi.h and link with pkg-config --cflags --libs cisivi.

Use Cases

Scripts and Operations

  • →Read columns and values from CSV exports in shell scripts and CI jobs, where cut and awk break on quoted commas.
  • →Filter, sort, and count the rows of reports, then print them as JSON for other tools or as a table for people.
  • →Join monthly exports into one file, convert semicolon-separated spreadsheet exports, or update one value in place.

Development

  • →Add CSV reading and writing to a C or C++ program with one small, dependency-free library.
  • →Read CSV from memory, a socket, or standard input through stream callbacks, and write rows one at a time.
  • →Let an AI coding assistant query and edit CSV files with exact commands instead of text edits.

Technical Specifications

LanguageC99
LicenseMIT
Version1.0.1
PlatformmacOS 11+, Linux (x64, ARM64, ARMv6+), Windows (x64, ARM64)
DependenciesStandard C library
Build SystemCMake 3.20+ or Make

Stop splitting CSV on commas.

Install Cisivi in one command and query your first CSV file in seconds.

View the source on GitHub, get the package on npm, read the documentation, or add the AI agent skill.