Search by

solvebeam / twinfield-cli

remcotolsma

Twinfield CLI brings Twinfield to your terminal. Free and open source.

Package info

github.com/solvebeam/twinfield-cli

Homepage

pkg:composer/solvebeam/twinfield-cli

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

v0.2.0 2026-11-12 14:11 UTC

This package is auto-updated.

Last update: 2026-11-12 14:12:32 UTC


README

Twinfield CLI brings Twinfield to your terminal. Free and open source.

The manual, with a page for each command, is on https://cli.twinfield.solvebeam.com/.

Log in to Twinfield once from the command line, then use that login in tests, examples and scripts:

composer require --dev solvebeam/twinfield-cli
vendor/bin/twf login
use SolveBeam\Twinfield\Cli\Credentials;
use SolveBeam\Twinfield\Twinfield;

$twinfield = Twinfield::create(Credentials::default());

foreach ($twinfield->offices()->list() as $office) {
    echo $office->code, ' ', $office->name, PHP_EOL;
}

It works like gcloud auth application-default login, aws sso login or gh auth login: the command line tool stores the login, and your code picks it up without knowing about OAuth.

You do not need a Twinfield client ID: by default the login goes through Twinfield Connect. The first login registers the Twinfield CLI with Twinfield Connect once per machine.

When to use it

  • Tests and examples that call the live Twinfield API.
  • Scripts you run yourself, such as an import or a report.
  • CI, with environment variables instead of the login (see below).

In an application where users log in themselves, use solvebeam/twinfield-connect or solvebeam/oauth2-twinfield and store the refresh tokens yourself.

Commands

vendor/bin/twf login           # log in with your browser
vendor/bin/twf login --manual  # paste the redirected URL yourself, e.g. over SSH
vendor/bin/twf login --rest    # also ask for all REST API scopes
vendor/bin/twf status          # show the logins
vendor/bin/twf token           # print a valid access token, e.g. for curl
vendor/bin/twf logout          # remove the login
vendor/bin/twf office list     # list the offices
vendor/bin/twf process-xml     # send an XML request
vendor/bin/twf deleted-transaction list --office=1000 # list the deleted transactions
vendor/bin/twf list            # show all commands
vendor/bin/twf login --help    # show the options of a command

The command is twf, after the twf. prefix Twinfield uses itself (twf.organisationCode). vendor/bin/twinfield is the same command under its long name.

login opens the Twinfield login in your browser and catches the redirect on http://localhost:8765/callback.

Offices

office list lists the offices (companies, administrations) you have access to, like gh repo list:

vendor/bin/twf office list                # all offices
vendor/bin/twf office list '*Holding*'    # search in code and name: * matches anything, ? one character
vendor/bin/twf office list --limit=10     # or -L 10
vendor/bin/twf office list --json         # JSON, e.g. for jq
vendor/bin/twf office list --profile=acme # the offices of another login

In a terminal the offices are a table. In a pipe they are tab-separated lines without a header, with the code, name, country and company ID:

vendor/bin/twf office list | cut -f1

XML requests

process-xml sends a request to the XML web services of Twinfield (ProcessXml), like gh api. With it you read, create and change anything these web services support:

vendor/bin/twf process-xml request.xml --office=1000

echo '<read><type>office</type><code>1000</code></read>' | vendor/bin/twf process-xml --office=1000

xml is the short name of process-xml: vendor/bin/twf xml request.xml.

The request comes from a file or from standard input; --office is the code of the office (company) the request is for. The response is printed as Twinfield returned it, and indented in a terminal.

When Twinfield does not process (all of) the request, the response is printed too: it has the messages (msg) on the elements they are about. The error goes to standard error and the exit status is 1.

Deleted transactions

deleted-transaction list lists the transactions that were deleted in an office, the newest deletion first, for example to keep a copy of the transactions in sync:

vendor/bin/twf deleted-transaction list --office=1000 --from=2026-11-01  # deleted since 1 November
vendor/bin/twf deleted-transaction list --office=1000 --day-book=BNK     # of one day book
vendor/bin/twf deleted-transaction list --office=1000 --limit=10         # the last 10 deletions
vendor/bin/twf deleted-transaction list --office=1000 --json             # JSON, e.g. for jq

--from and --to are about the date of deletion; both days are included. Twinfield has no paging here, so without --from you get all deleted transactions of the office.

In a terminal they are a table. In a pipe they are tab-separated lines without a header, with the day book, number, transaction date, moment of deletion, user and reason.

Profiles

Use a profile for each organisation:

vendor/bin/twf login --profile=acme
$twinfield = Twinfield::create(Credentials::default('acme'));

Or choose the profile with TWINFIELD_PROFILE=acme.

Your own Twinfield client

vendor/bin/twf login --client-id=… --client-secret=… --redirect-uri=http://localhost:8765/callback

The redirect URI must be registered with your client. Instead of the options you can set TWINFIELD_CLIENT_ID, TWINFIELD_CLIENT_SECRET and TWINFIELD_REDIRECT_URI.

Where the login is stored

In ~/.config/twinfield/credentials.json, or in $XDG_CONFIG_HOME/twinfield/ or $TWINFIELD_CONFIG_DIR/ when set. Only you can read the file (0600); on Windows the permissions of your user folder protect it.

The file holds the refresh token and the last access token. Credentials::default() uses the access token until it expires, then refreshes it and writes the new tokens back. Writes lock the file, so processes that run at the same time do not overwrite each other's refresh token.

CI and environment variables

When TWINFIELD_REFRESH_TOKEN is set, Credentials::default() uses it instead of the file. Credentials::default('acme') always uses the profile you name.

Variable
TWINFIELD_REFRESH_TOKEN The refresh token.
TWINFIELD_CONNECT_CLIENT_ID, TWINFIELD_CONNECT_CLIENT_SECRET The Twinfield Connect client, see credentials.json.
TWINFIELD_CLIENT_ID, TWINFIELD_CLIENT_SECRET Or your own Twinfield client.
TWINFIELD_CONNECT_URL Only for a Twinfield Connect you run yourself.
TWINFIELD_REDIRECT_URI Only when your client does not use http://localhost:8765/callback.

Tokens from environment variables are not written back.

License

The MIT License (MIT). See LICENSE.

Twinfield and Wolters Kluwer are trademarks of Wolters Kluwer. Their names are used only to refer to their products.