Search

    MENU

    Settings

    Markdown

    Without ZINN_DIR, Zinn reads the global ~/.zinn/settings.json and the nearest optional zinn.local.json in a codebase. They can choose the data directory, a default project, how long a write waits for a busy database and the telemetry mode. The global file can also set the telemetry limits and configure hooks. With ZINN_DIR, Zinn reads only settings.json inside that selected directory. Note that storage.directory does not cause settings from its target directory to be read.

    For the files and paths that make up a store, see Data and backups.

    Choose the data directory

    The first configured location wins:

    1. ZINN_DIR selects that directory for the operation.
    2. storage.directory in the nearest zinn.local.json selects a directory for the current codebase.
    3. storage.directory in ~/.zinn/settings.json selects the global directory.
    4. If none is set, Zinn uses ~/.zinn as its directory.

    If a ZINN_DIR is provided, Zinn reads only settings.json inside that directory. It does not read the home or codebase settings files. While the selected settings.json can set defaultProject, ZINN_DIR itself selects the directory.

    Without ZINN_DIR, Zinn looks for zinn.local.json from the current directory up to the Git root. Outside a Git repository, it checks only the current directory. It reads the global ~/.zinn/settings.json too, then merges the local file over it field by field. A local setting overrides the same global setting. You can omit fields in the local setting to inherit global values. The local settings file is not meant to be committed, as it can cause unexpected behavior on others’ Zinn setups who install the same repo with the tracked local setting.

    storage.directory is relative to the folder containing the file that sets it. A leading ~ or ~/ expands to your home directory. It names the Zinn directory, which contains data/zinn.sqlite, backups/, logs/, and telemetry/.

    The selected directory holds one database shared by all its projects. Choose a local directory outside network shares and synchronized folders. See safe storage and backups.

    A folder selected through ZINN_DIR or storage.directory must already exist. Create it with mkdir -p <path> before using it. Creating the first project or label creates the database inside an existing empty folder. With no explicit location, it also creates the default ~/.zinn folder. Until then, other commands fail with code not_found and entity database and create no database. In an existing folder, the failed run is still recorded in telemetry/ unless telemetry is off. An empty ZINN_DIR is refused. Help, version requests, and zinn info work with a missing folder.

    For example, this zinn.local.json selects a shared data directory and its default project:

    			
    				
    						
    						{
    	"$schema": "https://zinn.sh/schemas/settings/v1.json",
    	"defaultProject": "MDR",
    	"storage": {
    		"directory": "~/work/zinn-data"
    	}
    }
    					
    			
    		

    The $schema field is optional and gives editors a schema for autocomplete and validation. Zinn ignores it. Settings files are JSON without comments. Unknown keys, invalid JSON, and values of the wrong type stop normal commands with an error naming the file. Zinn does not fall back to defaults. A settings version changes only when a change would make existing settings files invalid. When ZINN_DIR is set, malformed home and codebase settings are not read.

    Choose a default project

    defaultProject names the project used when a command supports omitting its project key. Project keys are matched case-insensitively. An explicitly typed key takes precedence, then zinn.local.json, then the global settings file. With ZINN_DIR, only the selected directory’s settings.json can provide the default.

    The default applies to task create, task list, task search, project view, project column list, project edit, and project delete when their project key is omitted. A null value is not accepted. Without a default, task list and task search cover every project; the other commands require a key. A configured default that names a missing project causes a command that uses it to fail and identify the key and settings file. --all-projects makes task list and task search cover every project even when a default is configured; it works with --all or --archived and cannot be combined with a typed project key.

    The defaultProject setting applies only to commands that support an omitted key. For example, task-key commands use the project in the task key, and column creation, editing, and ordering require an explicit project key. See the CLI reference for command details.

    Wait for a busy database

    One command at a time can write to a database. A command that needs to write while another holds the lock waits, then fails with a storage error with reason busy if the lock is still held. busyTimeoutMs sets how long it waits, in milliseconds:

    			
    				
    						
    						{
    	"busyTimeoutMs": 60000
    }
    					
    			
    		

    It is a whole number from 0 to 2147483647 and defaults to 30000. 0 fails at once instead of waiting. zinn.local.json can set it, and the nearest one overrides the global file.

    Run hooks after changes

    hooks in the global settings file (~/.zinn/settings.json, or settings.json inside ZINN_DIR) lists commands that Zinn runs after each saved change:

    			
    				
    						
    						{
    	"hooks": {
    		"notify": { "command": "sh ~/.zinn/hooks/notify.sh", "timeout": 10 }
    	}
    }
    					
    			
    		

    Hooks run commands, so they are read only from the global settings file. A hooks key in zinn.local.json is a settings error like any other invalid setting, and hooks never run from the local settings file. See Hooks for what a hook receives and how failures are handled.

    Control local telemetry

    Zinn records local usage by default and sends nothing off the machine. See Telemetry for the records and their limits. The telemetry key has three fields, and a file can set any of those it is allowed to:

    			
    				
    						
    						{
    	"telemetry": {
    		"mode": "off",
    		"maxMegabytes": 50,
    		"maxAgeDays": 365
    	}
    }
    					
    			
    		
    • mode is local or off. off writes no new records and keeps existing files. Without a setting, mode is local, or off when the DO_NOT_TRACK environment variable is 1, following donottrack.sh. Only the value 1 counts. A telemetry.mode in a settings file overrides DO_NOT_TRACK, whichever way it is set.
    • maxMegabytes is a positive whole number of megabytes, each 1,048,576 bytes. It limits the total size of the record files and defaults to 100.
    • maxAgeDays is a positive whole number of days to keep records. It defaults to 90.

    zinn.local.json can set mode, and the nearest one overrides the global file. A mode applies only to records written by commands run in that codebase. maxMegabytes and maxAgeDays are read only from the global file, because the records they delete can come from any codebase. Either limit in zinn.local.json is a settings error like any other invalid setting. With ZINN_DIR, only that directory’s settings.json is read, and it can set all three fields.

    Inspect the selected store

    Use zinn info to inspect the selected store and settings without initializing or upgrading the database:

    			
    				
    						
    						zinn info
    					
    						
    						zinn info --json
    					
    			
    		

    The report includes the selected store directory and source, settings files and their state, default project, telemetry mode and folder, database path and schema state, and CLI, core, and runtime versions. Settings states are found, missing, error, or not-read when ZINN_DIR selects a different settings file. Database state is absent, empty, unmarked, current, older, newer, or unavailable.

    zinn info --json returns one object with stable top-level keys:

    • settingsFiles lists each inspected settings file with its path, source (env, global, or local), state, and either its parsed settings or an error. Unread home and codebase files with ZINN_DIR have state not-read and reason ZINN_DIR.
    • storage contains the selected directory, its source (env, local, global, or default), the settingsPath that chose it (or null for env and default), whether it exists, and an error.
    • defaultProject contains its key, the settingsPath that supplied it, and an error; the key and path are null when there is no configured default.
    • telemetry contains the resolved mode (off or local), its source (default, DO_NOT_TRACK, or settings), the settingsPath of the file that set the mode (null unless source is settings), maxMegabytes, maxAgeDays, the directory of the telemetry folder, whether it exists, the sizeBytes of the files directly inside it, and an error. A file that sets only maxMegabytes or maxAgeDays does not change source. The size is 0 when the folder is missing, because info never creates it. A path that is not a folder is reported with exists false, sizeBytes null and an error.
    • database contains the database path, its state, its version, the latestVersion supported by this CLI, and an error. The version is 0 for absent, empty, and unmarked states.
    • versions contains cli, core, and runtime (name and version).

    database.path resolves existing symbolic links and relative paths to an absolute destination. storage.directory records the configured directory. If database-path resolution fails, the report keeps the requested database path with state unavailable and an error.

    For example, when settings and the database can be inspected, the report has this shape:

    			
    				
    						
    						{
    	"settingsFiles": [
    		{
    			"path": "/home/me/.zinn/settings.json",
    			"source": "global",
    			"state": "found",
    			"settings": { "defaultProject": "DEMO" }
    		},
    		{ "path": "/work/app/zinn.local.json", "source": "local", "state": "missing" }
    	],
    	"storage": {
    		"directory": "/home/me/.zinn",
    		"source": "default",
    		"settingsPath": null,
    		"exists": true,
    		"error": null
    	},
    	"defaultProject": { "key": "DEMO", "settingsPath": "/home/me/.zinn/settings.json", "error": null },
    	"telemetry": {
    		"mode": "local",
    		"source": "default",
    		"settingsPath": null,
    		"maxMegabytes": 100,
    		"maxAgeDays": 90,
    		"directory": "/home/me/.zinn/telemetry",
    		"exists": true,
    		"sizeBytes": 21345,
    		"error": null
    	},
    	"database": {
    		"path": "/home/me/.zinn/data/zinn.sqlite",
    		"state": "current",
    		"version": 2,
    		"latestVersion": 2,
    		"error": null
    	},
    	"versions": {
    		"cli": "<installed CLI version>",
    		"core": "<installed core version>",
    		"runtime": { "name": "Node", "version": "<runtime version>" }
    	}
    }
    					
    			
    		

    When settings are unusable or a database cannot be inspected, info reports the errors and exits with code 0. unavailable means settings left the store undecided (path and version are null), or the selected file could not be read as a database (path is set, version is null, and error explains why). Every error is null when there is no problem. A settings error is carried on storage, defaultProject, telemetry, and database as well as its settingsFiles entry, so the same string can appear several times. The fields a settings file could have set are null. With ZINN_DIR, an unusable selected settings.json sets only defaultProject.error and telemetry.error, since the store is already chosen. SQLite may perform normal file housekeeping and crash recovery while info inspects a database.