looped.shDocs
Looped CLI

CLI command reference

Every looped command, its flags, and an example

This page lists every command in the Looped CLI. Run any command with --help to see the same flags in your terminal.

Conventions

A few rules apply across all commands:

  • Ids, not names. Flags like --project, --client and --section take an id. Each app has a lookup command that shows ids: looped track projects, looped track sections list, looped invoices clients, looped manage team list.
  • --json. Most commands print a table or a short message. Add --json to print the API's response as JSON instead.
  • --confirm. Commands that delete something or can't be undone refuse to run without --confirm. There's no interactive prompt, so scripts pass --confirm too. Without it, nothing is sent to Looped.
  • Dates. Dates are YYYY-MM-DD unless a flag says otherwise.
  • Comma-separated lists. Flags that take several values, like --status PAID,OVERDUE, take them as one comma-separated value.
  • Permissions. Each command needs the matching permission in your role. If you don't have it, the command fails and the error names the permission.

Account

looped login

Signs in through your browser and asks which company to use. See Signing in.

bash
looped login

looped logout

Removes your saved session.

bash
looped logout

looped whoami

Shows your user id, the selected company's id and your permissions for that company.

bash
looped whoami

Track

Commands for Looped Track. All of them live under looped track.

Time entries

looped track list

Lists your time entries for a day. Without flags, it shows today.

FlagDescription
--date <date>The day to list (YYYY-MM-DD). Defaults to today
--frequency <frequency>day, week or month. Widens the range around --date
--project <projectId>Only show entries for this project
--jsonPrint JSON
bash
looped track list --date 2026-09-21 --frequency week

looped track start <taskName>

Starts a timer for a new time entry. The entry is created in Looped straight away with a duration of one second, and the CLI remembers it in ~/.looped/track-timer.json until you stop it. Only one timer can run at a time.

FlagDescription
--project <projectId>Project to log the time against
--section <sectionId>Section to log the time against
--description <text>A longer description
--jsonPrint JSON
bash
looped track start "Homepage redesign" --project <projectId>

looped track stop

Stops the running timer and saves the elapsed time on the entry.

If the entry was deleted in the web app while the timer ran, stop fails but clears the timer so you can start a new one.

FlagDescription
--jsonPrint JSON
bash
looped track stop

looped track time get <id>

Shows one time entry.

FlagDescription
--jsonPrint JSON
bash
looped track time get <entryId>

looped track time update <id>

Changes a time entry. Only the fields you pass change.

FlagDescription
--task-name <name>New task name
--description <text>New description
--date <date>New date, as an ISO 8601 date-time
--duration <seconds>New duration, in seconds
--project <projectId>Move the entry to this project
--section <sectionId>Move the entry to this section
--jsonPrint JSON
bash
looped track time update <entryId> --duration 5400

looped track time delete <id>

Deletes a time entry.

FlagDescription
--confirmRequired
bash
looped track time delete <entryId> --confirm

Projects

looped track projects

Lists projects. Use it to find the id to pass to --project.

FlagDescription
--status <status>Only show projects with this status, such as ACTIVE
--search <query>Search by title or code
--jsonPrint JSON
bash
looped track projects --status ACTIVE --search website

looped track project create <title>

Creates a project. The CLI doesn't print the new project's id; run looped track projects --search "<title>" to find it.

FlagDescription
--code <code>Project code. Generated for you if you leave it out
bash
looped track project create "Website refresh" --code WEB

looped track project update <id>

Changes a project's title, code or status.

FlagDescription
--title <title>New title
--code <code>New code
--status <status>PENDING, ACTIVE, COMPLETED or ARCHIVED
bash
looped track project update <projectId> --status COMPLETED

looped track project delete <id>

Deletes a project. Looped only deletes a project that has no time entries.

FlagDescription
--confirmRequired
bash
looped track project delete <projectId> --confirm

Sections

Sections split a project into parts.

looped track sections list

Lists a project's sections.

FlagDescription
--project <projectId>Required. The project
--jsonPrint JSON
bash
looped track sections list --project <projectId>

looped track sections create <title>

Adds a section to a project.

FlagDescription
--project <projectId>Required. The project
--jsonPrint JSON
bash
looped track sections create "Design" --project <projectId>

looped track sections update <id> <title>

Renames a section.

FlagDescription
--jsonPrint JSON
bash
looped track sections update <sectionId> "Discovery"

looped track sections delete <id>

Deletes a section. Looped only deletes a section that has no time entries.

FlagDescription
--confirmRequired
bash
looped track sections delete <sectionId> --confirm

Tags

See Tags.

looped track tags list

Lists your company's tags.

FlagDescription
--jsonPrint JSON
bash
looped track tags list

looped track tags create <title>

Creates a tag.

FlagDescription
--jsonPrint JSON
bash
looped track tags create "billable"

looped track tags update <id> <title>

Renames a tag.

FlagDescription
--jsonPrint JSON
bash
looped track tags update <tagId> "non-billable"

looped track tags delete <id>

Deletes a tag. Looped only deletes a tag that isn't on any time entries.

FlagDescription
--confirmRequired
bash
looped track tags delete <tagId> --confirm

Todos

looped track todos list

Lists todos.

FlagDescription
--filter <filter>all, active or completed. Defaults to all
--jsonPrint JSON
bash
looped track todos list --filter active

looped track todos create <title>

Creates a todo.

FlagDescription
--description <text>A longer description
--project <projectId>Project
--section <sectionId>Section
--priority <priority>P1 (highest) to P4 (lowest)
--due-date <date>Due date, ISO 8601
--jsonPrint JSON
bash
looped track todos create "Send wireframes" --priority P1 --due-date 2026-10-01

looped track todos get <id>

Shows one todo.

FlagDescription
--jsonPrint JSON
bash
looped track todos get <todoId>

looped track todos update <id>

Changes a todo. Only the fields you pass change.

FlagDescription
--title <title>New title
--description <text>New description
--completedMark it done
--not-completedMark it not done
--project <projectId>New project
--section <sectionId>New section
--priority <priority>P1 to P4
--due-date <date>New due date, ISO 8601
--jsonPrint JSON
bash
looped track todos update <todoId> --completed

looped track todos delete <id>

Deletes a todo.

FlagDescription
--confirmRequired
bash
looped track todos delete <todoId> --confirm

Preferences

These are your company's Track settings. get and update always print JSON.

looped track preferences get

Shows the company's time-tracking preferences.

bash
looped track preferences get

looped track preferences update

Changes the company's time-tracking preferences. Only the flags you pass change.

FlagDescription
--time-unit <unit>HOUR or MINUTE
--time-step <n>Rounding step in the chosen unit, or none to stop rounding
--ghost-text / --no-ghost-textTurn ghost-text suggestions on or off
--auto-log / --no-auto-logTurn logging time when a todo is completed on or off
bash
looped track preferences update --time-unit MINUTE --time-step 15

Dashboard

looped track dashboard

Prints a weekly or monthly time summary as JSON.

FlagDescription
--scope <scope>me or team. team needs a role that can see everyone's time
--period <period>weekly or monthly
--week-end <date>Any date inside the week or month you want (YYYY-MM-DD)
bash
looped track dashboard --period monthly --week-end 2026-09-15

Reports

Reports are pivot tables of time data, the same ones you build in Reports. A report's definition (its schema) is JSON with rows, columns, values and filters. The easiest way to get one is to build the report in Track, then copy its schema from looped track reports get <id> --json.

looped track reports list

Lists the saved reports you can see.

FlagDescription
--jsonPrint JSON
bash
looped track reports list

looped track reports get <id>

Shows one saved report.

FlagDescription
--jsonPrint JSON
bash
looped track reports get <reportId> --json

looped track reports run

Runs a report without saving it. Unless your role lets you see everyone's time, the results only include your own time.

FlagDescription
--schema <json>The full report schema as JSON
--rows <fields>Comma-separated row fields. Overrides rows in --schema
--columns <fields>Comma-separated column fields. Overrides columns in --schema
--start-date <date>Start date, ISO 8601
--end-date <date>End date, ISO 8601
--jsonPrint JSON
bash
looped track reports run --schema "$(cat report.json)" \
  --start-date 2026-09-01 --end-date 2026-09-30

looped track reports save <name>

Saves a report definition so you and others can run it again.

FlagDescription
--schema <json>Required. The full report schema as JSON
--allowed-roles <roles>Comma-separated roles that can see it: OWNER, ADMIN, MEMBER
--allowed-users <userIds>Comma-separated user ids that can see it
--jsonPrint JSON
bash
looped track reports save "Hours by project" --schema "$(cat report.json)" \
  --allowed-roles OWNER,ADMIN

looped track reports update <id>

Replaces a saved report's name and schema. Only Owners, Admins and the report's creator can change it.

FlagDescription
--name <name>Required. The report name
--schema <json>Required. The full report schema as JSON
--allowed-roles <roles>Comma-separated roles that can see it
--allowed-users <userIds>Comma-separated user ids that can see it
--jsonPrint JSON
bash
looped track reports update <reportId> --name "Hours by project" \
  --schema "$(cat report.json)"

looped track reports delete <id>

Deletes a saved report. Only Owners, Admins and the report's creator can delete it.

FlagDescription
--confirmRequired
bash
looped track reports delete <reportId> --confirm

Invoices

Commands for Looped Invoices. All of them live under looped invoices.

Invoice statuses are PENDING, PAID, PAID_PARTIAL, EXPIRED and OVERDUE.

Invoices

looped invoices list

Lists invoices.

FlagDescription
--status <statuses>Comma-separated statuses, such as PAID,OVERDUE
--client <clientId>Only this client's invoices
--from <date>Issued on or after this date
--to <date>Issued on or before this date
--jsonPrint JSON
bash
looped invoices list --status OVERDUE --from 2026-07-01

looped invoices get <id>

Shows one invoice.

FlagDescription
--jsonPrint JSON
bash
looped invoices get <invoiceId>

looped invoices create

Creates an invoice. Invoices have too many fields for one flag each, so you pass the whole invoice as a JSON object, either inline with --data or from a file with --data-file. Pass one or the other, not both. The invoice needs a clientId (or a client object) and at least one line item. If the JSON doesn't match what Looped expects, the error says which field is wrong. The API reference lists every field.

FlagDescription
--data <json>The invoice as inline JSON
--data-file <path>Path to a JSON file with the invoice
--jsonPrint JSON
bash
looped invoices create --data '{
  "clientId": "<clientId>",
  "lineItems": [{ "description": "Consulting", "unitPrice": 100, "quantity": 5 }]
}'

looped invoices update <id>

Changes an invoice. Takes the same --data or --data-file JSON as create.

FlagDescription
--data <json>The changes as inline JSON
--data-file <path>Path to a JSON file with the changes
--jsonPrint JSON
bash
looped invoices update <invoiceId> --data-file invoice.json

looped invoices delete <id>

Permanently deletes an invoice.

FlagDescription
--confirmRequired
--jsonPrint JSON
bash
looped invoices delete <invoiceId> --confirm

looped invoices mark-paid <id>

Marks an invoice as paid.

FlagDescription
--jsonPrint JSON
bash
looped invoices mark-paid <invoiceId>

looped invoices send <id>

Emails an invoice to its client.

FlagDescription
--jsonPrint JSON
bash
looped invoices send <invoiceId>

looped invoices pdf <id>

Downloads an invoice as a PDF.

FlagDescription
--output <path>Required. Where to save the PDF
--downloadAsk the server to send it as an attachment
bash
looped invoices pdf <invoiceId> --output invoice.pdf

looped invoices dashboard

Shows a summary of revenue, outstanding invoices and top clients.

FlagDescription
--jsonPrint the full dashboard data
bash
looped invoices dashboard

Statements

looped invoices statements

Builds a statement for one client. By default it prints the statement as JSON. For a PDF, a CSV or a Xero-ready CSV, pass --format and --output.

FlagDescription
--client <clientId>Required. The client
--from <date>Start of the period. Defaults to the start of the year
--to <date>End of the period. Defaults to today
--status <statuses>Comma-separated invoice statuses to include
--format <format>json (default), pdf, csv or xero
--output <path>Where to save the file. Required unless --format is json
--downloadAsk the server to send it as an attachment
bash
looped invoices statements --client <clientId> --format pdf --output statement.pdf

Clients

See Clients.

looped invoices clients

Lists clients. Use it to find the id to pass to --client.

FlagDescription
--jsonPrint JSON
bash
looped invoices clients

looped invoices client get <id>

Shows one client.

FlagDescription
--jsonPrint JSON
bash
looped invoices client get <clientId>

looped invoices client update <id>

Replaces a client's details. This isn't a partial update: the JSON must include at least name, email, line1 and postalCode every time.

FlagDescription
--data <json>The client as inline JSON
--data-file <path>Path to a JSON file with the client
--jsonPrint JSON
bash
looped invoices client update <clientId> --data-file client.json

looped invoices client delete <id>

Permanently deletes a client.

FlagDescription
--confirmRequired
--jsonPrint JSON
bash
looped invoices client delete <clientId> --confirm

Quotes

All quote commands live under looped invoices quotes. Quote statuses are DRAFT, SENT, ACCEPTED, REJECTED, EXPIRED and CONVERTED.

looped invoices quotes list

Lists quotes.

FlagDescription
--status <statuses>Comma-separated statuses, such as SENT,ACCEPTED
--client <clientId>Only this client's quotes
--from <date>Issued on or after this date
--to <date>Issued on or before this date
--jsonPrint JSON
bash
looped invoices quotes list --status SENT

looped invoices quotes get <id>

Shows one quote.

FlagDescription
--jsonPrint JSON
bash
looped invoices quotes get <quoteId>

looped invoices quotes create

Creates a quote. Like invoices create, it takes the whole quote as JSON.

FlagDescription
--data <json>The quote as inline JSON
--data-file <path>Path to a JSON file with the quote
--jsonPrint JSON
bash
looped invoices quotes create --data-file quote.json

looped invoices quotes update <id>

Changes a quote.

FlagDescription
--data <json>The changes as inline JSON
--data-file <path>Path to a JSON file with the changes
--jsonPrint JSON
bash
looped invoices quotes update <quoteId> --data-file quote.json

looped invoices quotes delete <id>

Permanently deletes a quote.

FlagDescription
--confirmRequired
--jsonPrint JSON
bash
looped invoices quotes delete <quoteId> --confirm

looped invoices quotes send <id>

Emails a quote to its client.

FlagDescription
--jsonPrint JSON
bash
looped invoices quotes send <quoteId>

looped invoices quotes set-status <id>

Marks a quote as accepted or rejected. A converted quote can't change status.

FlagDescription
--status <status>Required. ACCEPTED or REJECTED
--jsonPrint JSON
bash
looped invoices quotes set-status <quoteId> --status ACCEPTED

looped invoices quotes convert <id>

Turns a quote into an invoice. The quote's status becomes CONVERTED.

FlagDescription
--jsonPrint JSON
bash
looped invoices quotes convert <quoteId>

looped invoices quotes pdf <id>

Downloads a quote as a PDF.

FlagDescription
--output <path>Required. Where to save the PDF
--downloadAsk the server to send it as an attachment
bash
looped invoices quotes pdf <quoteId> --output quote.pdf

Manage

Commands for your company's account. All of them live under looped manage. Most need an Owner or Admin; see Roles & permissions.

Members and invites

looped manage team list

Lists the company's members. The ID column is the member id that remove and change-role take.

FlagDescription
--jsonPrint JSON
bash
looped manage team list

looped manage team invite <email>

Invites someone to the company by email.

FlagDescription
--role <role>admin or member. Defaults to member
--roles <ids>Comma-separated role ids they start with, such as track.member,invoices.admin, or a custom role's id. If you leave it out, a Member gets track.member and an Admin gets none
--jsonPrint JSON

Built-in role ids include track.admin, track.member, invoices.admin, financials.admin and payroll.admin. See Roles & permissions.

bash
looped manage team invite sam@example.com --role member --roles track.member,invoices.admin

looped manage team invites

Lists pending invites.

FlagDescription
--jsonPrint JSON
bash
looped manage team invites

looped manage team revoke-invite <inviteId>

Cancels a pending invite.

FlagDescription
--jsonPrint JSON
bash
looped manage team revoke-invite <inviteId>

looped manage team change-role <memberId>

Changes a member's base role, their roles, or both. Pass at least one of --role and --roles.

FlagDescription
--role <role>owner, admin or member. Only an Owner can make someone an Owner
--roles <ids>Their full list of role ids, comma-separated. This replaces the list they have. An empty string (--roles "") removes all their roles
--jsonPrint JSON
bash
looped manage team change-role <memberId> --role admin
looped manage team change-role <memberId> --roles track.admin,invoices.admin

looped manage team remove <memberId>

Removes a member from the company. They need a new invite to come back.

FlagDescription
--confirmRequired
--jsonPrint JSON
bash
looped manage team remove <memberId> --confirm

looped manage team leave

Removes you from the selected company. You need a new invite to come back.

FlagDescription
--confirmRequired
--jsonPrint JSON
bash
looped manage team leave --confirm

Company settings

looped manage settings show

Shows the company's name, VAT number, currency and other settings.

FlagDescription
--jsonPrint JSON
bash
looped manage settings show

looped manage settings update

Changes company settings. Only the flags you pass change; pass at least one.

FlagDescription
--name <name>Company name
--vat-number <vatNumber>VAT number
--currency <currency>Currency code, such as USD
--auto-add-members <true|false>Whether new members are added to this company automatically. Takes the word true or false
--jsonPrint JSON
bash
looped manage settings update --currency ZAR --auto-add-members false

looped manage settings friendly-id <friendlyId>

Changes the company's friendly id, the short name used in its URLs.

FlagDescription
--jsonPrint JSON
bash
looped manage settings friendly-id acme-studio

looped manage settings address show

Shows the company's billing address. This is also the address on your invoices.

FlagDescription
--jsonPrint JSON
bash
looped manage settings address show

looped manage settings address set

Sets the company's billing address. Creates it if there isn't one yet, or replaces it. Lines you leave out are cleared.

FlagDescription
--line1 <line1>Required. Address line 1
--line2 <line2>Address line 2
--line3 <line3>Address line 3
--postal-code <postalCode>Required. Postal code
--jsonPrint JSON
bash
looped manage settings address set --line1 "12 Long Street" --line2 "Cape Town" --postal-code 8001

looped manage settings bank show

Shows the company's bank account details.

FlagDescription
--jsonPrint JSON
bash
looped manage settings bank show

looped manage settings bank set

Sets the company's bank account details. Creates them if there aren't any yet, or replaces them. All five details are required.

FlagDescription
--account-holder <name>Required. Account holder name
--account-no <accountNo>Required. Account number
--account-type <accountType>Required. Account type
--bank-name <bankName>Required. Bank name
--branch-code <branchCode>Required. Branch code
--jsonPrint JSON
bash
looped manage settings bank set --account-holder "Acme Studio" --account-no 123456789 \
  --account-type Cheque --bank-name "Example Bank" --branch-code 250655

looped manage settings delete-team

Permanently deletes the selected company. This can't be undone. Only an Owner can do it, and Looped refuses if the company has an active subscription or it's your only company. See Danger zone.

FlagDescription
--confirmRequired
--jsonPrint JSON
bash
looped manage settings delete-team --confirm

API keys

These commands manage the company's API keys. They need the "Manage API keys" permission, which Owners and Admins have.

looped manage keys list

Lists the company's API keys, with their permissions, whether they're revoked, and when they expire.

FlagDescription
--jsonPrint JSON
bash
looped manage keys list

looped manage keys create

Creates an API key. The CLI prints the raw key once. Copy it then: it can't be shown again.

FlagDescription
--name <name>Required. A label for the key
--scope <scopes>Required. Comma-separated permissions, such as track:time.read,track:time.write
--expires-at <isoDate>Expiry date, ISO 8601. Leave it out for a key that doesn't expire
--jsonPrint JSON
bash
looped manage keys create --name "Reporting service" \
  --scope track:time.read,invoices:invoices.read --expires-at 2027-01-01

looped manage keys revoke <id>

Revokes an API key. Anything using it stops working straight away.

FlagDescription
--jsonPrint JSON
bash
looped manage keys revoke <keyId>

Are you an AI? Visit llms.txt — these docs as plain markdown.

On this page

ConventionsAccountlooped loginlooped logoutlooped whoamiTrackTime entrieslooped track listlooped track start <taskName>looped track stoplooped track time get <id>looped track time update <id>looped track time delete <id>Projectslooped track projectslooped track project create <title>looped track project update <id>looped track project delete <id>Sectionslooped track sections listlooped track sections create <title>looped track sections update <id> <title>looped track sections delete <id>Tagslooped track tags listlooped track tags create <title>looped track tags update <id> <title>looped track tags delete <id>Todoslooped track todos listlooped track todos create <title>looped track todos get <id>looped track todos update <id>looped track todos delete <id>Preferenceslooped track preferences getlooped track preferences updateDashboardlooped track dashboardReportslooped track reports listlooped track reports get <id>looped track reports runlooped track reports save <name>looped track reports update <id>looped track reports delete <id>InvoicesInvoiceslooped invoices listlooped invoices get <id>looped invoices createlooped invoices update <id>looped invoices delete <id>looped invoices mark-paid <id>looped invoices send <id>looped invoices pdf <id>looped invoices dashboardStatementslooped invoices statementsClientslooped invoices clientslooped invoices client get <id>looped invoices client update <id>looped invoices client delete <id>Quoteslooped invoices quotes listlooped invoices quotes get <id>looped invoices quotes createlooped invoices quotes update <id>looped invoices quotes delete <id>looped invoices quotes send <id>looped invoices quotes set-status <id>looped invoices quotes convert <id>looped invoices quotes pdf <id>ManageMembers and inviteslooped manage team listlooped manage team invite <email>looped manage team inviteslooped manage team revoke-invite <inviteId>looped manage team change-role <memberId>looped manage team remove <memberId>looped manage team leaveCompany settingslooped manage settings showlooped manage settings updatelooped manage settings friendly-id <friendlyId>looped manage settings address showlooped manage settings address setlooped manage settings bank showlooped manage settings bank setlooped manage settings delete-teamAPI keyslooped manage keys listlooped manage keys createlooped manage keys revoke <id>