Minimal symbolic CLI calculator powered by SymPy
Project description
phil
A minimal command-line calculator for exact arithmetic, symbolic differentiation, integration, algebraic equation solving, and ordinary differential equations.
Powered by SymPy.
Why phil
phil is designed to be the first-stop calculator for quick terminal math, homework, and symbolic workflows — before reaching for WolframAlpha, a Python REPL, or a graphing calculator.
It prioritizes exactness, speed, and discoverability. When it rewrites your input, it says so.
Install
Requires uv.
uv tool install philcalc
- PyPI: https://pypi.org/project/philcalc/
- Source: https://github.com/sacchen/phil
- Tutorial: TUTORIAL.md
- Roadmap: ROADMAP.md
Quick Start
phil '1/3 + 1/6'
phil '10^100000 + 1 - 10^100000'
phil 'd(x^3 + 2*x, x)'
phil 'int(sin(x), x)'
phil "ode y' = y, y(0)=1"
phil '(1 - 25e^5)e^{-5t} + (25e^5 - 1)t e^{-5t} + t e^{-5t} ln(t)'
Or open the REPL (phil) and try these in order:
1/3 + 1/6d(x^3 + 2*x, x)int(sin(x), x)solve(x^2 - 4, x)N(pi, 20)
If stuck, run :examples or :h.
Usage
One-shot
phil '<expression>'
phil --format pretty '<expression>'
phil --format json '<expression>'
phil --no-simplify '<expression>'
phil --explain-parse '<expression>'
phil --latex '<expression>'
phil --latex-inline '<expression>'
phil --latex-block '<expression>'
phil --wa '<expression>'
phil --wa --copy-wa '<expression>'
phil --color always '<expression>' # also: auto (default), never
phil "ode y' = y"
phil "ode y' = y, y(0)=1"
phil "linalg solve A=[[2,1],[1,3]] b=[1,2]"
phil "linalg rref A=[[1,2],[2,4]]"
phil "linalg det A=[[1,2],[3,4]]"
phil "linalg inv A=[[1,2],[3,4]]"
phil "linalg eig A=[[1,2],[3,4]]"
phil "linalg nullspace A=[[1,2],[2,4]]"
phil :examples
phil :tutorial
phil :ode
phil :linalg
Interactive REPL
phil
phil> <expression>
REPL commands:
:h/:helpshow strict command reference?,??,???progressive feature discovery (quick start, speed shortcuts, advanced demos):examplesshow runnable expression patterns:tutorial/:t/:tourstart interactive tutorial mode:odeshow ODE cheat sheet and templates:linalg/:lashow linear algebra cheat sheet and templates:next/:repeat/:donecontrol interactive tutorial mode (Enteradvances while tutorial is active):v/:versionshow current version:update/:checkcompare current vs latest version and print update command:q/:quit/:xexit
The REPL starts with phil vX.Y.Z REPL [status] (:h help, :t tutorial) on interactive terminals.
When an update is available, startup prints uv tool upgrade philcalc on the next line.
Errors are prefixed with E: followed by a hint: line.
Most evaluation errors also include hint: try WolframAlpha: <url> (suppressed for some local guardrail failures).
Session keeps ans (last result) and supports assignment: A = Matrix([[1,2],[3,4]]).
Inline CLI options work per-expression: --latex d(x^2, x).
For readable ODE solving, prefer ode ... input: ode y' = y.
Parsing and Input Style
These normalizations apply in all modes (including --strict):
{}->()ln(t)->log(t)!factorialsin^2(x)accepted- Leibniz shorthand accepted (
d(sin(x))/dx,df(t)/dt) - ODE shorthand accepted (
dy/dx = y,y' = y,y'' + y = 0,y'(0)=0) - LaTeX-style ODE accepted (
\frac{dy}{dx} = y,\frac{d^2y}{dx^2} + y = 0) - Common LaTeX wrappers and commands are normalized:
$...$,\(...\),\sin,\cos,\ln,\sqrt{...},\frac{a}{b}
Relaxed parsing (default) also enables implicit multiplication:
2x->2*xsinx->sin(x)(with ahint:notice)
Use --strict to require explicit multiplication:
phil --strict '2*x'
Undefined symbols raise errors.
Built-in helper names are reserved for evaluation and cannot be reassigned.
In ODE input, prefer explicit multiplication (20*y instead of 20y) for predictable parsing.
Exact Arithmetic and Reliability
phil defaults to exact symbolic arithmetic.
Cancellable huge expressions stay fast and exact:
10^10000000000 + 1 - 10^10000000000 -> 1
2^(2^20) + 1 - 2^(2^20) -> 1
Non-cancellable explosive growth fails fast with a recovery hint rather than hanging:
10^10000000000 + 1
2^(2^(2^20))
100001!
factorial(10^10)
Ambiguous shorthand is rejected with explicit guidance:
sin x^2
Precedence note:
-2^2->-(2^2)- Use
(-2)^2for a negative base squared.
Output and Interop
--format jsonprints a compact JSON object withinput,parsed, andresult; diagnostics stay onstderr--format prettyimproves matrix readability--explain-parseprintshint: parsed as: ...onstderr--color auto|always|nevercontrols ANSI output on diagnostic lines;NO_COLORalso respectedstdoutstays result-only, so pipes and scripts remain predictable- Complex expressions print a WolframAlpha equivalent link by default;
--waforces it,--copy-wacopies it to the clipboard
Updates
uv tool upgrade philcalc
In REPL:
- Startup prints a status badge on interactive terminals; when an update is available a second line prints the upgrade command
:versionshows your installed version:update/:checkshow current version, latest known release, and update command
For release notifications on GitHub, use "Watch" -> "Custom" -> "Releases only" on the repo page.
Examples
$ phil '1/3 + 1/6'
1/2
$ phil 'd(x^3 + 2*x, x)'
3*x**2 + 2
$ phil 'int(sin(x), x)'
-cos(x)
$ phil 'solve(x^2 - 4, x)'
[-2, 2]
$ phil 'N(pi, 30)'
3.14159265358979323846264338328
$ phil --latex 'd(x^2, x)'
2 x
$ phil --latex-inline 'd(x^2, x)'
$2 x$
$ phil --latex-block 'd(x^2, x)'
$$
2 x
$$
$ phil --format pretty 'Matrix([[1,2],[3,4]])'
[1 2]
[3 4]
Reference
Core operations
| Operation | Syntax |
|---|---|
| Derivative | d(expr, var) |
| Integral | int(expr, var) |
| Solve equation | solve(expr, var) |
| Solve ODE | dsolve(Eq(...), func) |
| Equation | Eq(lhs, rhs) |
| Numeric eval | N(expr, digits) |
| Integer GCD/LCM | gcd(a, b), lcm(a, b) |
| Primality / factorization | isprime(n), factorint(n) |
| Rational parts | num(expr), den(expr) |
| Matrix determinant | det(Matrix([[...]])) or linalg det A=[[...]] |
| Matrix inverse | inv(Matrix([[...]])) or linalg inv A=[[...]] |
| Matrix rank | rank(Matrix([[...]])) or linalg rank A=[[...]] |
| Matrix eigenvalues | eigvals(Matrix([[...]])) or linalg eig A=[[...]] |
| Matrix RREF | rref(Matrix([[...]])) or linalg rref A=[[...]] |
| Matrix nullspace | nullspace(Matrix([[...]])) or linalg nullspace A=[[...]] |
| Solve linear system (Ax=b) | msolve(Matrix([[...]]), Matrix([...])) or linalg solve A=[[...]] b=[...] |
| Symbolic linear solve | linsolve((Eq(...), Eq(...)), (x, y)) |
Notes:
For Ax=b, use linalg solve A=[[...]] b=[...] or msolve(A, b) instead of solve(A=..., b=...).
Common symbols
x, y, z, t, pi, e, f
Functions
sin, cos, tan, exp, log, sqrt, abs, gamma, atan2, binomial, limit, series, factor, expand
Exact arithmetic helpers
gcd, lcm, isprime, factorint, num, den
Symbol helpers
symbols("A B C")returns a tuple of symbolsS("A")is shorthand forSymbol("A")
Matrix helpers
Matrix, eye, zeros, ones, det, inv, rank, eigvals, rref, nullspace, msolve, linsolve
Syntax notes
^is exponentiation (x^2)- Function exponent notation is accepted (
sin^2(x),cos^2(x)) !is factorial (5!)- Relaxed mode (default) allows implicit multiplication (
2x); use--strictto require2*x d(expr)/int(expr)infer the variable when exactly one symbol is present- Leibniz shorthand is accepted:
d(sin(x))/dx,df(t)/dt - ODE shorthand is accepted:
dy/dx = y,y' = y,y'' + y = 0,y'(0)=0 - LaTeX-style ODE shorthand is accepted:
\frac{dy}{dx} = y,\frac{d^2y}{dx^2} + y = 0 name = exprassigns in the REPL session (ansis always the last result)- Built-in helper names are reserved and cannot be reassigned
- Undefined symbols raise an error
Development
From a local clone:
uv tool install . # install locally
uv run --group dev pytest # run tests
uv run --group dev pytest -m "not integration" # fast local loop
scripts/checks.sh # full quality gate
CI runs via GitHub Actions. License is MIT. See CONTRIBUTOR.md for contribution guide and release process.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file philcalc-0.2.7.tar.gz.
File metadata
- Download URL: philcalc-0.2.7.tar.gz
- Upload date:
- Size: 64.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
06339a2d832e4882e31720469e431c274c32f03d869a4e5c1a632501a44aec2d
|
|
| MD5 |
c84f3e8b2f3b6fdb71d8f01413048ebc
|
|
| BLAKE2b-256 |
91705b169bd7388122c12cfb9f259ccea0f7cb13bcbf41802888a9f9944652ff
|
File details
Details for the file philcalc-0.2.7-py3-none-any.whl.
File metadata
- Download URL: philcalc-0.2.7-py3-none-any.whl
- Upload date:
- Size: 27.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ba038d0221e47fc0b6e646cd3853bf778f33347aaac3f5d9ac0aec88a53966b5
|
|
| MD5 |
3fc972e5037c2123f0cf8e472b6af58a
|
|
| BLAKE2b-256 |
2365eac5237212c321aa3d30c4afa65403bbc0c81e0d818c2f19103794c782e4
|