- Rust 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| src | ||
| tests | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| README.md | ||
jea
jea is a small, opinionated wrapper around Jujutsu (jj) and Forgejo's tea CLI.
I like jj. I like Forgejo. I do not like remembering a pile of Git / jj git / tea commands just to move work around.
So jea gives the workflows I actually use short, predictable names.
It is built with walts-cli.
Requirements
jea expects these commands to be available in PATH:
jj
tea
walts-cli checks for them before dispatching commands.
tea must also have a configured Forgejo login with the permissions needed for the operation you are running.
Basic usage
jea <command> [args] [options]
Show available commands:
jea --help
Show command-specific help:
jea publish --help
Everyday jj wrappers
Status
jea status
jea st
Runs jj st.
New change
jea new
jea n
Create a new change with a description:
jea new -m "Implement the thing"
jea new --message="Implement the thing"
Edit a change
jea edit <change>
jea e <change>
Example:
jea e xowwnkro
Squash
jea squash
Split
jea split
Resolve
jea resolve
Fetch
jea fetch
Runs jj git fetch.
Push
jea push
Runs jj git push.
Repository setup
Initialize
jea init
init bootstraps a jj repository and its main bookmark.
A Forgejo repository can also be supplied:
jea init -r jea
jea init --repo=jea
When a repository is supplied, jea also adds the Forgejo remote before bootstrapping main.
jeais currently opinionated around my Forgejo setup, including thebedrawk.netSSH host andwaltowner.
Remotes
The remote> commands wrap jj git remote.
Because > is shell redirection syntax, quote these command names in shells that interpret it.
Add my Forgejo origin
jea 'remote>forgejo' jea
This currently builds:
ssh://[email protected]/walt/jea.git
and adds it as origin.
Add a remote
jea 'remote>add' origin ssh://[email protected]/user/repo.git
List remotes
jea 'remote>list'
Remove a remote
jea 'remote>remove' origin
Rename a remote
jea 'remote>rename' origin upstream
Change a remote URL
jea 'remote>set-url' origin ssh://[email protected]/user/repo.git
Forgejo repositories and issues
List repositories
jea repos
Create a repository
jea 'create>repo' my-project
Useful options:
jea 'create>repo' my-project --private
jea 'create>repo' my-project --init
jea 'create>repo' my-project -O walt
jea 'create>repo' my-project -d "Some repo"
Supported options:
-O, --owner repository owner
-d, --description repository description
-p, --private make repository private
-i, --init initialize the repository
Create an issue
jea 'create>issue' "Parser bug"
With a description:
jea 'create>issue' "Parser bug" -d "Something exploded"
Target a specific repository:
jea 'create>issue' "Parser bug" -r walt/jea
Add labels:
jea 'create>issue' "Parser bug" -L bug,parser
Supported options:
-d, --description issue description
-L, --labels comma-separated labels
-r, --repo repository slug or path
If the current repository has a Forgejo remote that tea can identify, --repo is usually unnecessary.
Workflow commands
This is where jea becomes more than a pile of aliases.
Sync
jea sync
The default workflow is:
jj git fetch
jj rebase -d trunk@origin
Override the destination:
jea sync -t main@origin
jea sync --target=main@origin
Publish
Publish the current jj change as a Forgejo pull request:
jea publish <bookmark>
Example:
jea publish jea-workflows
With a title and base:
jea publish jea-workflows \
-t "Add sync, publish, create, and remote workflows" \
-b main
publish currently does:
jj bookmark set <bookmark> -r @
jj git push --bookmark <bookmark>
tea pr create --head <bookmark> --base <base> --title <title>
The default base is trunk.
If no title is provided, the bookmark name is used.
Approve a pull request
jea approve <pr>
Example:
jea approve 4
Forgejo may reject approval of your own pull request, which is expected server-side behavior.
Merge a pull request
jea merge <pr>
Example:
jea merge 5
After merging, jea automatically fetches the updated remote state with jj.
The default merge style is merge.
Override it with:
jea merge 5 -s squash
jea merge 5 --style=rebase
Supported styles are those provided by tea:
merge
rebase
squash
rebase-merge
Example workflow
A normal feature flow can look like:
jea new -m "Add cool feature"
# hack hack hack
jea st
jea publish cool-feature \
-t "Add cool feature" \
-b main
After review / CI:
jea merge <pr-number>
Then start the next change:
jea new -m "Next thing"
For someone else's PR:
jea approve <pr-number>
jea merge <pr-number>
Why create>repo instead of subcommands?
jea intentionally treats hierarchy as naming, not parser architecture.
These are flat command names:
create>repo
create>issue
remote>add
remote>list
remote>remove
That keeps the CLI parser simple while still visually grouping related operations.
Testing
Run the full test suite:
cargo test
The tests focus on the CLI contract without actually creating repositories, opening PRs, rebasing history, or calling Forgejo.
The project has dedicated coverage for:
basic CLI behavior
wrapper commands
repository / issue creation
remote commands
sync workflows
publish workflows
PR approve / merge parsing
Real jj / tea behavior is smoke-tested manually against Forgejo.
Status
jea is intentionally small and personal.
The goal is not to replace every jj or tea command. Raw jj and tea remain available for advanced work.
jea exists to make the common path pleasant.