Package Exports
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (freelo-cli) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
freelo-cli
Command-line interface for Freelo.io — manage projects, tasklists, tasks, comments, time entries, and files without leaving the terminal.
Status: early access. Authentication, configuration, and an introspectable command surface are shipped. Resource commands (projects, tasklists, tasks, comments, time entries, files) are landing one spec at a time.
Install
npm install -g freelo-cli
# or
pnpm add -g freelo-cliRequires Node.js 20.11 or newer.
Use
freelo --version # prints the installed version
freelo --help # shows available commands (human-readable)
freelo --introspect # full command tree as JSON (agent-friendly)
freelo help <cmd> --output json # JSON help for a single command or subtreeThe CLI is agent-first: when stdout is not a TTY, every data-returning command emits a versioned JSON envelope ({ "schema": "freelo.<resource>.<op>/vN", "data": ... }). Pipe it into jq, capture it from a script, or hand it to your agent runner.
Use freelo auth login once to store credentials (env vars FREELO_API_KEY + FREELO_EMAIL work too — they take precedence and skip the keychain entirely, which is the recommended path for CI and agent workflows).
Commands
auth
freelo auth login— Store credentials for a Freelo profile and verify them.freelo auth logout— Remove stored credentials for a Freelo profile.freelo auth whoami— Show the currently authenticated user.
comments
freelo comments add [input]— Post a single comment to a task from --message, --from-file, --editor, or stdin (-). Note: when the target task has no prior comments, the API converts this into the task description; usefreelo tasks description setfor explicit description writes.freelo comments edit [id...]— Overwrite an existing comment's content. Single id or batch (positional..., --ids, or --stdin NDJSON). Content from --message, --from-file, --editor, or stdin (-). Endpoint is POST /comment/{id} (yaml :2634 — POST for historical reasons). freelo comments list— List comments across all projects, tasks, documents, files and links the caller can see.
config
freelo config get <key>— Get the current value and source of a configuration key. Read-only keys (e.g. 'apiKey') return '[redacted]'.freelo config list— List all configuration keys with current values and sources.freelo config profiles— List all configured profiles.freelo config resolve— Print the merged effective configuration with optional per-leaf source annotation.freelo config set <key> <value>— Set a configuration key. Writable keys: output, color, profile, apiBaseUrl, verbose. Read-only keys (email, apiKey) must be updated via 'freelo auth login'.freelo config unset <key>— Remove a configuration key from the user conf store. Read-only keys cannot be unset via 'config'; use 'freelo auth logout' for credentials.freelo config use <profile>— Switch the active profile. The profile must already exist (created via 'freelo auth login'). No network call is made — use auth whoami to verify credentials afterward.
files
freelo files download <uuid>— Download a file by UUID. Streams the binary body to a local path (atomic write) or to stdout. Refuses to overwrite an existing destination unless --force is set.freelo files list— List every directory, link, file, and document the caller can see (paginated). Filter by --project / --type. No --task filter — endpoint does not surface one.freelo files upload <path...>— Upload one or more local files to Freelo. Returns a UUID per file. Optionally attach the uploads to a task by posting a comment with embedded references (the only documented attach mechanism — yaml :3876).
help
freelo help [commandPath...]— Print the command tree as JSON (--output json) or as the same text as --help (default).
labels
freelo labels attach— Attach one or more labels to a project (fetch-or-create per name). One POST per --name. Defaults to private labels (caller-only); use --public for shared labels.freelo labels delete [id...]— Hard-delete one or more project labels GLOBALLY (across all projects). Destructive — requires --yes (non-TTY) or interactive confirmation (TTY). 404 treated as idempotent (already-deleted).freelo labels detach— Detach one or more labels from a project. Idempotent — detaching a label that is not attached is a successful no-op (404 → already_in_target_state: true).freelo labels list— List the caller's available project labels (their private labels plus public labels from accessible projects). No filters in v1 —--projectis deferred until the API surfaces an attachments map.freelo labels rename <id>— Rename, recolor, or toggle private/public on an existing project label. At least one change flag is required.
notifications
freelo notifications list— List notifications addressed to the calling user (paginated). Filter by --unread / --project / --type. Server-side ACL-filtered.freelo notifications read [id...]— Mark notifications as read. Server-side idempotent: re-marking an already-read notification is a safe 200. Supports positional... / --ids / --stdin / --all-unread. freelo notifications unread [id...]— Mark notifications as unread (re-surface). Server-side idempotent: re-marking is safe. Supports positional... / --ids / --stdin.
projects
freelo projects list— List projects in the chosen scope. Default scope is 'owned'.freelo projects show <id>— Show one project's full detail, with optional side-cars.
reports
freelo reports delete [id...]— Delete one or more work reports. Destructive — requires --yes (non-TTY) or interactive confirmation (TTY). 404 (and 400 with "not found" body) treated as idempotent already-deleted; 400 with UserCannotDeleteWorkReport surfaces as a hard ACL error.freelo reports edit [id]— Edit an existing work report (minutes / note / date). At least one change flag is required. Single-mode (+ flags) or NDJSON batch via --stdin. freelo reports list— List work reports (time entries) across all projects, with optional task / project / worker / date filters.freelo reports log— Log a finalized work report on a task (bypasses the live-timer flow). Single-mode (--task / --minutes …) or NDJSON batch via --stdin.
subtasks
freelo subtasks add— Create a subtask (taskcheck) under a parent task (single or NDJSON batch via --stdin). Note: Freelo's API auto-falls-back from a smart subtask (full task with worker, due date, etc.) to a simple taskcheck (a checkbox row with only a name) when the parent's tasklist can't host smart ones. The response envelope'sdata.storage_formfield reflects which form was actually persisted;data.input_ignored[]lists fields you set that the server discarded on the simple path.freelo subtasks list— List subtasks (taskchecks) under one parent task, paginated.
task-labels
freelo task-labels attach— Attach one or more labels to a task. Each --name and --uuid becomes one entry in a single bulk POST. --hex applies to name-mode entries only (UUID-mode uses the existing label's color).freelo task-labels create— Bulk-create task-label definitions in the caller account. Server-side fetch-or-create onname(case-sensitive) — re-running with the same names is a safe no-op. The API does not report new vs. reused.freelo task-labels detach— Detach one or more labels from a task. --name without --hex removes ALL labels with that name (aggressive); add --hex to scope to a specific (name,color) pair. UUID-mode is precise — removes exactly that label. Server is idempotent — detaching a label not on the task is a successful no-op.
tasklists
freelo tasklists list— List tasklists across all projects you can see, optionally filtered to one project.freelo tasklists show <id>— Show one tasklist's detail, with optional assignable-workers side-car.
tasks
freelo tasks create— Create a task in a tasklist (single or NDJSON batch via --stdin).freelo tasks delete [id...]— Soft-delete one or more tasks. Destructive — requires --yes (non-TTY) or interactive confirmation (TTY). 404-after-delete is treated as idempotent already-deleted.freelo tasks description get <id>— Print one task's rich-text description.freelo tasks description set <id> [input]— Replace one task's rich-text description from a file, an interactive editor, or stdin (upsert).freelo tasks edit <id>— Partially update a task: name, due date, worker, priority, and label diff.freelo tasks finish [id...]— Mark tasks as finished. Idempotent: tasks already finished aren't re-POSTed.freelo tasks list— List tasks across all projects (default) or scoped to one project + tasklist.freelo tasks move [id]— Move a task between tasklists (single id) or move many tasks via NDJSON --stdin batch.freelo tasks reopen [id...]— Reopen finished tasks (move back to active). Idempotent: already-active tasks are skipped.freelo tasks show <id>— Show one task's full detail, with optional side-cars.
time
freelo time edit— Edit the active time tracking session in flight (--task / --clear-task / --note). At least one flag is required. Returns 409 with a friendly hint when no session is running.freelo time start— Start a time tracking session (singleton per user). Both --task and --note are optional; omit --task for general work. A second start while one is already running returns 409 with a friendly hint.freelo time status— Print the caller's currently-running time tracking session, or { active: false } when no timer is running. Returns exit 0 in both cases.freelo time stop— Stop the active time tracking session and emit the resulting work report. Returns 409 with a friendly hint when no session is running.
The block above is generated from freelo --introspect by scripts/check-readme.mjs and verified in CI. Run pnpm fix:readme to refresh it after adding or changing a command.
The freelo help command (e.g. freelo help auth --output json) is intentionally not listed above — it's a meta-command that introspect excludes.
Develop
pnpm install
pnpm dev -- --version # run the entry directly via tsx
pnpm build # bundle to dist/freelo.js
pnpm test # vitest
pnpm lint && pnpm typecheck
pnpm check:readme # verify the autogen Commands block matches `freelo --introspect`
pnpm fix:readme # rewrite the autogen Commands block in placeConventional Commits are enforced by a commit-msg hook. Add a changeset (pnpm changeset) for any user-visible change.
Process
This repository uses an agentic SDLC. See .claude/docs/sdlc.md (interactive) and .claude/docs/autonomous-sdlc.md (autonomous via /auto).
License
MIT